C++ 如何在C++;OpenCV?
我想对灰度图像的强度值应用k均值聚类。我对如何将像素表示成向量感到困惑。所以如果我的图像是C++ 如何在C++;OpenCV?,c++,opencv,C++,Opencv,我想对灰度图像的强度值应用k均值聚类。我对如何将像素表示成向量感到困惑。所以如果我的图像是hxw像素,那么我的向量应该是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
hxw
像素,那么我的向量应该是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)
}
但是它一直在打印result=0
,尽管我特别要求它不要:)我如何访问这些值
Mat
转换到InputArray
,但是您可以(并且应该)只传递一个Mat
对象,其中请求了InputArray
。有关详细说明,请参阅Mat
对象,您需要img.at(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;
}
#包括
使用名称空间cv;
int main()
{
Mat1b grayImg=imread(“路径到图像”,imread\U灰度);
Mat1f数据(grayImg.rows*grayImg.cols,1);
对于(int r=0;r
您不需要将Mat转换为InputArray。InputArray只是一个接受cv::Mat和std::vector的包装类。所以只要通过一个垫子,它接受一个输入,你就会没事了。关于这个错误。。。让我检查一下,你能把完整的代码贴出来吗?这里有很多遗漏的变量…@Miki,我省略了前面的部分,很抱歉。现在它应该有所有相关的代码。我确信输入是正确的,我绘制了灰色img,它看起来和预期的一样。其他3个变量初始化为cv::Mat
。感谢您提供的信息,InputArray是不必要的。所以我可以用一个cv::Mat
大小[H*W x 1]
(或转置),对吗?贴出答案,它应该能回答你所有的问题。让我知道。非常感谢你!这很有效。不过,我有两个问题。1.您如何决定使用Mat1b
、Mat1f
等中的哪一个?我的第二个问题是,如何打印结果的像素?因为我怀疑它们可能有值1或2,而我想将它们转换为0和1。我想补充一下我在问题中尝试过的东西,我真的非常感谢你最后的帮助。再次感谢!您可能还对我的新问题感兴趣:)1)根据文档。读取代码更容易,并且当类型不正确时,代码中会出现干净的错误。使用at()访问Mat时,您必须知道类型。结果中的值已经是簇中心的灰度值,因此在[0255]中。您可以使用imshow查看结果图像。如果希望图像带有标签,则需要创建Mat1i,并将bestLabels中的值放入其中。
#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;
}