如何在C ++ OpenCV中将图像(Mat)转换为inputArray? [英] How to convert image (Mat) into inputArray in C++ OpenCV?

查看:1414
本文介绍了如何在C ++ OpenCV中将图像(Mat)转换为inputArray?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想对灰度图像的强度值应用k均值聚类.我真的很困惑如何将像素表示为矢量.因此,如果我的图像是H x W像素,那么我的矢量应该是H*W尺寸.

I want to apply k-means clustering on the intensity values of a grayscale image. I'm really confused on how to represent the pixels into a vector. So if my image is H x W pixels, then my vector should be H*W dimensional.

我尝试过的是:

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的新手,所以不确定如何使用这些功能.我在此处找到了这段代码.例如,为什么我们使用.at<float>,另一些帖子说灰度图像像素存储为<char>?我越来越困惑,所以任何帮助将不胜感激:)

I'm new to OpenCV so I'm not sure how to use any of these functions. I found this code here. For example, why do we use .at<float>, some other post says that grayscale image pixels are stored as <char>s ?? I'm getting confused more and more, so any help would be appreciated :)

谢谢!

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

Thanks to Miki, I found the right way to do it. But one final question, how do I see the contents of cv::Mat1b result? I tried printing them like this :

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,即使我特别要求它不要:)如何访问这些值?

But it keeps printing result=0, even though I specifically ask it not to :) How do I access the values?

推荐答案

  1. 您不需要从Mat转换为InputArray,但是您可以(并且应该)只传递请求InputArrayMat对象.请参阅此处以获取详细说明

  1. You don't need to convert from Mat to InputArray, but you can (and should) just pass a Mat object where an InputArray is requested. See here for a detailed explanation

kmeans 接受一个I​​nputArray,即应该是带有浮点坐标的N维点的数组.

kmeans accepts an InputArray, that should be an array of N-Dimensional points with float coordinates is needed.

对于Mat对象,您需要img.at<type>(row, col)才能访问像素的值.但是,您可以使用Mat_,它是Mat的模板版本,可以在其中修复类型,因此您可以像img(r,c)一样访问值.

With Mat objects, you need img.at<type>(row, col) to access value of the pixel. You can, however, use Mat_ that is a templated version of Mat where you fix the type, so you can access the value just like 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 ++ OpenCV中将图像(Mat)转换为inputArray?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆