AnswerOpenCV(0826-0901)一周佳作欣赏
1、OpenCV to detect how missing tooth in equipment
Hello everyone. I am just starting with OpenCV and still a bit lost.
Is OpenCV helpful to detect the position of a missing object (tooth for example)?
I would like to build a code to analyze an image of an equipment and detect which tooth is missing and its position.
For example in the image attached below of an equipment that has 9 teeth normally: the code should show a message that the 2nd tooth is missing.
Is this possible with OpenCV? If yes, where do I start?
Attached you will find the figure. missing tooth.PNG
寻找这种类似齿轮的问题,可以在hull距的前提下,进行专门的处理。有兴趣可以继续研究,当然它这个图像质量比较差。
相关函数
convexityDefects
https://docs.opencv.org/master/d3/dc0/group__imgproc__shape.html#gada4437098113fd8683c932e0567f47ba
defects.png
提供教程:https://docs.opencv.org/master/d5/d45/tutorial_py_contours_more_functions.html
2、Detect equipment in desired position
Hello everyone!
Is It possible to evaluate some pictures and save them Just when the object is in some desired position?
For example: monitoring a vídeo of an equipment that moves in and out of the scene. I would like to detect the time when the equipment is fully in the scene and then save It in a desired folder.
Thanks a Lot and have a great weekend
这个问题问的有点不清楚,也可能是非英语为母语的人提出的。实际上他想说明的、寻求的应该是一个MOG问题。
一旦项目由静态的图片提升到了动态的视频,在维度上面就有了提高,因此也会出现许多新的问题。
3、Does findContours create duplicates
Hi,I'm considering a binary image from which I extract its edges using cv::Canny. Consequently, I perform cv::findContours, storing all the contours points coordinates in a
vector < vector < Point > >
I noticed that the number of pixels (Points) in this structure is greater than the number of pixels I get by computing
vector<point> white_pixels;
findNonZero(silhouette, white_pixels);
on the same image.
Therefore I'm wondering if this happens because findContours includes duplicate points in its result or because findNonZero is less precise.
E.g. on a 200x200 sample image with the first method I get 1552 points while with the second I get 877.
In case the first hypothesis is correct, is there a way to either ignore the duplicates or remove them?
非常关键的一题,许多大神给出解答
a、
In case of a Canny edge image findContours will find most of the contour points twice, because the line width is only 1 and findContours is looking for closed contours.
To remove duplicates you can map the contour points to an empty (zero) image.For every contour point add 1 at the image position and only copy the contour point to your new contour vector if the value at this position is zero. That would be the easiest way I think.
flag offensive link
Comments
Thanks! Actually, I did what you suggested using the same sample image and also counting how many pixels were set to 1 (without repetitions). I ended up with having exactly 877 white pixels in the new Mat::zeros image. At this point, i think the result I get by using "findNonZero" is correct, accurate and in this case more efficient since I can avoid the double for loop I used for mapping the contour points for this test.
b、My first answer was wrong. @matman answer is good but I think problem is in blurred image.
If you don't blur enough image you will have many double points. You shape become a line but at beginning your shape could be a rectangle.
if you find double point in your contour may be you have to increase blurring (shape like 8 could be a problem). For fractal shape (or with a large rugosity) it is difficult to delete those points.
In this example I use :surface rectangle 6 (width 3 and height 2)
canny witout blurring Image 0
canny with blur size 3 image 1
Canny with blur size 5 image 2
image description
Source file
{
Mat x = Mat::zeros(20,20,CV_8UC1);
Mat result = Mat::zeros(20,20,CV_8UC3);
vector<Vec3b> c = { Vec3b(255, 0, 0), Vec3b(0,255,0),Vec3b(0,0,255),Vec3b(255, 255, 0),Vec3b(255, 0, 255),Vec3b(0, 255, 255) };
for (int i=9;i<=10;i++)
for (int j = 9; j <= 11; j++)
{
x.at<uchar>(i,j)=255;
result.at<Vec3b>(i,j)=Vec3b(255,255,255);
}
imwrite("square.png",x);
Mat idx;
findNonZero(x,idx);
cout << "Square surface " << idx.rows<<endl;
vector<vector<vector<Point> >> contours(3);
vector<Vec4i> hierarchy;
double thresh=1;
int aperture_size=3;
vector<Mat> xx(3);
vector<Mat> dst(3);
for (size_t i = 0; i < xx.size(); i++)
{
if (i==0)
xx[i]=x.clone();
else
blur(x, xx[i], Size(static_cast<int>(2*i+1),static_cast<int>(2*i+1)));
Canny(xx[i], dst[i],thresh, thresh, 3,true );
namedWindow(format("canny%d",i),WINDOW_NORMAL);
namedWindow(format("result%d",i),WINDOW_NORMAL);
imshow(format("canny%d",i),dst[i]);
findContours(dst[i],contours[i], hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_NONE, Point(0, 0));
}
namedWindow("original image",WINDOW_NORMAL);
imshow("original image",x);
/*
Mat dx,dy,g;
Sobel(x, dx, CV_16S, 1, 0, aperture_size, 1, 0, BORDER_REPLICATE);
Sobel(x, dy, CV_16S, 0, 1, aperture_size, 1, 0, BORDER_REPLICATE);
namedWindow("gradient modulus",WINDOW_NORMAL);
g = dx.mul(dx) + dy.mul(dy);
imshow("gradient modulus",g);
findContours(x,contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_NONE, Point(0, 0));
cout << "#contours : " << contours.size()<<endl;
if (contours.size() > 0)
{
for (size_t i = 0; i < contours.size(); i++)
{
cout << "#pixel in contour of original image :"<<contours[i].size()<<endl;
for (size_t j=0;j<contours[i].size();j++)
cout << contours[i][j] << "*";
cout<<endl;
drawContours(result, contours, i, c[i]);
}
}*/
size_t maxContour=0;
for (size_t k = 0; k < 3; k++)
{
cout << "#contours("<<k<<") : " << contours[k].size()<<endl;;
if (maxContour<contours[k].size())
maxContour= contours[k].size();
if (contours[k].size() > 0)
{
for (size_t i = 0; i<contours[k].size();i++)
{
cout << "#pixel in contour using canny with original image :"<<contours[i].size()<<endl;
for (size_t j=0;j<contours[k][i].size();j++)
cout << contours[k][i][j] << "*";
cout<<endl;
}
}
else
cout << "No contour found "<<endl;
}
int index=0;
while (true)
{
char key = (char)waitKey();
if( key == 27 )
break;
if (key == '+')
{
index = (index+1)%maxContour;
}
if (key == '-')
{
index = (index-1);
if (index<0)
index = maxContour-1;
}
vector<Mat> result(contours.size());
for (size_t k = 0; k < contours.size(); k++)
{
result[k] = Mat::zeros(20,20,CV_8UC3);
for (int ii=9;ii<=10;ii++)
for (int jj = 9; jj <= 11; jj++)
{
result[k].at<Vec3b>(ii,jj)=Vec3b(255,255,255);
}
if (index<contours[k].size())
drawContours(result[k], contours[k], static_cast<int>(index), c[index]);
else
cout << "No Contour "<<index<<" in image "<<k<<endl;
imshow(format("result%d",k),result[k]);
}
cout << "Contour "<<index<<endl;
}
exit(0);
}
但是对于今天的我来说,分析重复轮廓的意义在哪里了?很多时候,我都只是找最大的外围轮廓就可以的。
4、FindContours Duplicate Points
I am using OpenCV 3.4.1 with VS2015 C++ on a Win10 platform.
My question relates to findContours and whether that should be returning duplicate points within a contour.
For example, I have a test image like this:
image description
I do Canny on it and then I run findContours like this:
findContours(this->MaskFrame,this->Contours,this->Hierarchy,CV_RETR_EXTERNAL,CV_CHAIN_APPROX_NONE);
When I check the resulting contours like this:
for (int x = 0; x < Images->Contours.size(); x++)
for (int y = 0; y < Images->Contours[x].size(); y++)
for (int z = y + 1; z < Images->Contours[x].size(); z++)
if (Images->Contours[x][y] == Images->Contours[x][z])
printf("Contours duplicate point: x: %d, y: %d z: %d\n", x, y, z);
I can see there there are many/hundreds of duplicate points within a given contour.
image description
The presence of the duplicates seems to cause a problem with the drawContours function.
Nevertheless, this image shows that 6 contours were detected with ~19,000 points comprising all the contours, the largest contour has ~18,000 points, but there are 478 points that are duplicated within a contour.
However, this only seems to occur if the total number of points in a given contour is fairly large, e.g., > 2000 points.If I arrange the image so that no contour has more than ~2000 points, as below, then there are no duplicates.
image description
In this image, there are 11 contours, there are ~10,000 points comprising all the contours, with the largest contour having ~1,600 points, and no duplicates.
Before I try and get deep into findContours or something else, I thought I would ask: anyone have any ideas why I am seeing duplicate points within a contour?
Thanks for any help.
这里的具体运用,可能就是问题3的意义所在:通过轮廓分析来获得定量数据。
5、how to find the REAL width and height of contours
这道题目是我问的,而且也给出了最优回答,应该说是有价值的。
there is a image of 3 shapes image description
int main( int argc, char** argv )
{
//read the image
Mat img = imread("e:/sandbox/leaf.jpg");
Mat bw;
bool dRet;
//resize
pyrDown(img,img);
pyrDown(img,img);
cvtColor(img, bw, COLOR_BGR2GRAY);
//morphology operation
threshold(bw, bw, 150, 255, CV_THRESH_BINARY);
//bitwise_not(bw,bw);
//find and draw contours
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
findContours(bw, contours, hierarchy, CV_RETR_LIST, CV_CHAIN_APPROX_NONE);