gpt4 book ai didi

c++ - OpenCV - 如何计算照片中的物体?

转载 作者:行者123 更新时间:2023-11-28 05:54:33 24 4
gpt4 key购买 nike

我尝试对照片中的物体进行计数,但无法得到正确的结果。

我试试这段代码 http://opencv-code.com/tutorials/count-and-segment-overlapping-objects-with-watershed-and-distance-transform/

This is result

可以看到左图有9个物体,我运行代码后得到右图有11个物体。我用 ncomp 引入了 MessageBoxW,你可以看到 ncomp 得到了 11,而不是 9。

我搜索了很多但找不到另一个代码工作给我带来了 9 的结果。

我希望有人修复我应该使用它的代码,或者链接到我可以使用它并获得许多对象的正确结果的代码。

这是我使用的代码:

cv::Mat src = cv::imread("c:\\pic\\test.jpg");
if (!src.data)
return -1;

cv::imshow("src", src);

// Create binary image from source image
cv::Mat bw;
cv::cvtColor(src, bw, CV_BGR2GRAY);
cv::threshold(bw, bw, 40, 255, CV_THRESH_BINARY);
cv::imshow("bw", bw);

// Perform the distance transform algorithm
cv::Mat dist;
cv::distanceTransform(bw, dist, CV_DIST_L2, 3);

// Normalize the distance image for range = {0.0, 1.0}
// so we can visualize and threshold it
cv::normalize(dist, dist, 0, 1., cv::NORM_MINMAX);
cv::imshow("dist", dist);

// Threshold to obtain the peaks
// This will be the markers for the foreground objects
cv::threshold(dist, dist, .5, 1., CV_THRESH_BINARY);
cv::imshow("dist2", dist);

// Create the CV_8U version of the distance image
// It is needed for cv::findContours()
cv::Mat dist_8u;
dist.convertTo(dist_8u, CV_8U);

// Find total markers
std::vector<std::vector<cv::Point> > contours;
cv::findContours(dist_8u, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
int ncomp = contours.size();

// Create the marker image for the watershed algorithm
cv::Mat markers = cv::Mat::zeros(dist.size(), CV_32SC1);

// Draw the foreground markers
for (int i = 0; i < ncomp; i++)
cv::drawContours(markers, contours, i, cv::Scalar::all(i+1), -1);

// Draw the background marker
cv::circle(markers, cv::Point(5,5), 3, CV_RGB(255,255,255), -1);
cv::imshow("markers", markers*10000);

// Perform the watershed algorithm
cv::watershed(src, markers);

// Generate random colors
std::vector<cv::Vec3b> colors;
for (int i = 0; i < ncomp; i++)
{
int b = cv::theRNG().uniform(0, 255);
int g = cv::theRNG().uniform(0, 255);
int r = cv::theRNG().uniform(0, 255);

colors.push_back(cv::Vec3b((uchar)b, (uchar)g, (uchar)r));
}

// Create the result image
cv::Mat dst = cv::Mat::zeros(markers.size(), CV_8UC3);

// Fill labeled objects with random colors
for (int i = 0; i < markers.rows; i++)
{
for (int j = 0; j < markers.cols; j++)
{
int index = markers.at<int>(i,j);
if (index > 0 && index <= ncomp)
dst.at<cv::Vec3b>(i,j) = colors[index-1];
else
dst.at<cv::Vec3b>(i,j) = cv::Vec3b(0,0,0);
}
}

cv::imshow("dst", dst);

wchar_t buffer[256];
wsprintfW(buffer, L"%d", ncomp);
MessageBoxW(nullptr, buffer, buffer, MB_OK);

cv::waitKey(0);
return 0;

提前致谢

最佳答案

您的算法计算由分水岭算法标记的对象。您给出的示例有 5 个对象和 5 个分水岭标签,因此它工作正常。但是您看到您的图像有 9 个对象但有 11 个分水岭标签。您应该在应用分水岭之前计算对象。实际上,您不需要应用分水岭,因为您的图像非常清晰,可以分割和计算对象。您只需将图像从彩色图像转换为二进制。之后找到并计算轮廓。代码如下。如果您不想应用扩张,您可以使用 contours_eroded.size() 获得对象的数量。这将在侵 eclipse 后为您提供数字。如果您不想应用任何形态学过程,您可以应用对二值图像进行 findcontour 函数,可以得到其轮廓的大小。

int main () {   
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
Rect bounding_rect;
Mat dst,bin;

Mat src = imread("example.jpg", CV_LOAD_IMAGE_COLOR); // reads image from file


cvtColor(src,dst,CV_BGR2GRAY); // converts image from rgb(src) to gray level (dst)
threshold(dst,bin,40,255,THRESH_BINARY); // Tresholds image with level = 40 from gray level(dst) to binary (bin)
findContours(bin,contours, hierarchy,CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE ); // finds contours on bin image

Scalar color( 255,255,255 );
for( int i = 0; i< contours.size(); i++ ) // iterate through each contour.
{
if((contourArea(contours[i],false))>100){ // if counter area >100 pixel draw it on ero which is new image variable
drawContours( bin, contours, i , color, CV_FILLED, 8, hierarchy ); //Draw contours on itself as filled
}
}

findContours( bin, contours, hierarchy,CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE );

for( int i = 0; i< contours.size(); i++ ) // iterate through each contour.
{
bounding_rect=boundingRect(contours[i]); //Bound and Draw rectangle each object which detected at the end on src(original image)
rectangle(src, bounding_rect, Scalar(0,255,0),3, 8,0);
}
namedWindow("Binary",CV_WINDOW_NORMAL);
imshow("Binary",src);
cout<<contours.size();
waitKey(0);
return 0;
}

关于c++ - OpenCV - 如何计算照片中的物体?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34478402/

24 4 0
文章推荐: c++ - 从字符串转换为 int vector 时出错
文章推荐: c++ - 找不到 vector 使用中的 fatal error
文章推荐: c++ - 如何使用 Microsoft 链接器工具链接静态 MFC 库
文章推荐: html - 从数组中拉取数据到
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com