c++ - 如何在 C++ OpenCV 中将图像 (Mat) 转换为 inputArray?

标签 c++ opencv

我想对灰度图像的强度值应用 k 均值聚类。我真的很困惑如何将像素表示为 vector 。所以如果我的图像是 H x W像素,那么我的 vector 应该是H*W立体的。

我试过的是:

int myClass::myFunction(const cv::Mat& img)
{
    cv::Mat grayImg;    
    cvtColor(img, grayImg, CV_RGB2GRAY);    
    cv::Mat bestLabels, centers, clustered;
    cv::Mat p = cv::Mat::zeros(grayImg.cols*grayImg.rows, 1, CV_32F);
    int i = -1;
    for (int c = 0; c<img.cols; c++) {
        for (int r = 0; r < img.rows; r++) {
            i++;
            p.at<float>(i, 0) = grayImg.at<float>(r, c);

        }
    }
// I should have obtained the vector in p, so now I want to supply it to k-means: 
int K = 2;
    cv::kmeans(p, K, bestLabels,
        cv::TermCriteria(CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 10, 1.0),
        3, cv::KMEANS_PP_CENTERS, centers);
// Since K=2, I want to obtain a binary image with this, so the same operation needs to be reversed (grayImg -> p , then bestLabels -> binaryImage)
}

但是我收到一个错误:Unhandled exception at 0x00007FFD76406C51 (ntdll.dll) in myapp.exe

我是 OpenCV 的新手,所以我不确定如何使用这些函数中的任何一个。我找到了这段代码 here .比如我们为什么要用.at<float> ,其他一些帖子说灰度图像像素存储为 <char> ??我越来越困惑,所以任何帮助将不胜感激:)

谢谢!

编辑

感谢 Miki,我找到了正确的方法。但最后一个问题是,我如何查看 cv::Mat1b result 的内容? ?我试过像这样打印它们:

for (int r = 0; r < result.rows; ++r)
    {
        for (int c = 0; c < result.cols; ++c)
        {
            result(r, c) = static_cast<uchar>(centers(bestLabels(r*grayImg.cols + c)));
            if (result(r, c) != 0) {
                std::cout << "result = " << result(r, c) << " \n";
            }               
        }
    }

但它一直打印result=0 ,即使我明确要求它不要 :) 我如何访问这些值?

最佳答案

  1. 您不需要从 Mat 进行转换至 InputArray ,但你可以(也应该)只传递一个 Mat InputArray 所在的对象被要求。参见 here详细解释

  2. kmeans接受一个 InputArray,它应该是一个具有浮点坐标的 N 维点数组。

  3. Mat对象,你需要 img.at<type>(row, col)访问像素的值。但是,您可以使用 Mat_那是 Mat 的模板版本固定类型的位置,因此您可以像 img(r,c) 一样访问值.

所以最终的代码将是:

#include <opencv2\opencv.hpp>
using namespace cv;


int main()
{
    Mat1b grayImg = imread("path_to_image", IMREAD_GRAYSCALE);

    Mat1f data(grayImg.rows*grayImg.cols, 1);
    for (int r = 0; r < grayImg.rows; r++)
    {
        for (int c = 0; c < grayImg.cols; c++)
        {
            data(r*grayImg.cols + c) = float(grayImg(r, c));

        }
    }

    // Or, equivalently
    //Mat1f data;
    //grayImg.convertTo(data, CV_32F);
    //data = data.reshape(1, 1).t();


    // I should have obtained the vector in p, so now I want to supply it to k-means: 
    int K = 8;
    Mat1i bestLabels(data.size(), 0); // integer matrix of labels
    Mat1f centers;                    // float matrix of centers
    cv::kmeans(data, K, bestLabels,
        cv::TermCriteria(CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 10, 1.0),
        3, cv::KMEANS_PP_CENTERS, centers);


    // Show results
    Mat1b result(grayImg.rows, grayImg.cols);
    for (int r = 0; r < result.rows; ++r)
    {
        for (int c = 0; c < result.cols; ++c)
        {
            result(r, c) = static_cast<uchar>(centers(bestLabels(r*grayImg.cols + c)));
        }
    }

    imshow("Image", grayImg);
    imshow("Result", result);
    waitKey();

    return 0;
}

关于c++ - 如何在 C++ OpenCV 中将图像 (Mat) 转换为 inputArray?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32976118/

相关文章:

c++ - 如何防止过度打字

C++ 将 vector 项转换为单个字符串错误?

c++ - 需要有关在 VS2010 中运行程序的帮助

python - 如何使用相机参数在 OpenGL 中正确设置投影和模型 View 矩阵

python - 如何使用 python 和 opencv 去除图像中对象的锯齿状边缘

c++ - 游戏服务器是否需要特定于正在玩的游戏的服务器代码,或者它们只是在客户端之间交换 IP 地址?

c++ - (void) sizeof (0[array]) 是什么意思?

c++ - 无法将空的初始值设定项分配给 unique_ptrs 的 vector

OpenCV:对不同的图像尺寸使用单应性

c++ - OpenCV 未解析的外部符号 - 需要其他库吗?