Python和OpenCV。如何检测图像中的所有(填充)圆形/圆形对象? [英] Python and OpenCV. How do I detect all (filled)circles/round objects in an image?

查看:2129
本文介绍了Python和OpenCV。如何检测图像中的所有(填充)圆形/圆形对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图制作一个程序,它打开一张图片,扫描它的圆/圆形并返回坐标,以便我可以使用 cv.Circle 函数来在检测到的圆上绘制圆圈。



我的问题是:如何使用 cv.HoughCircles()



使用页面,我发现了如何检测这些圆圈(这让我花了很多时间来发现,因为我不了解像阈值这样的术语,而Python的OpenCV文档非常差,几乎没有。不幸的是,在该页面上它没有显示如何提取从创建的 CvMat 中检测到的每个圈子的信息。如何提取这些信息/是否有其他方式(例如,使用 MemoryStorage())?



是我的代码到目前为止:

$ $ p $ 导入cv,opencv

def main():


im = cv.LoadImageM(Proba.jpg)

gray = cv.CreateImage(cv.GetSize(im),8,1)
边缘= cv.CreateImage(cv.GetSize(im),8,1)

cv.CvtColor(im,gray,cv.CV_BGR2GRAY)
cv.Canny(灰色,边缘,50 ,200,3)
cv.Smooth(灰色,灰色,cv.CV_GAUSSIAN,9,9)

storage = cv.CreateMat(im.rows,1,cv.CV_32FC3)

cv.HoughCircles(边缘,存储,cv.CV_HOUGH_GRADIENT,2,gray.height / 4,200,100)
#现在,假设它找到了圆圈,我该如何提取信息?
print storage.r


$ b $ if if __name__ =='__main__':
main()

另外, HoughCircles 的最后两个参数需要具备什么值才能让我检测真正的小圆圈(如屏幕上的3毫米)?

谢谢大家的时间和精力试图帮助我!



我正在处理的图像是这样的:

解决方案

最后两个参数似乎被传递给 cv.Canny(),这意味着从 cv.HoughCircles()中调用 cv.Canny() 。我对此不太确定。



至于尺寸,它好像接下来的两个参数(在 200,100之后) code>默认为 0 ,这可能意味着检测到所有尺寸。



从C ++示例的源代码中,我也可以猜测你不需要做Canny边缘检测:

  #include< cv.h> 
#include< highgui.h>
#include< math.h>

使用namespace cv;

int main(int argc,char ** argv)
{
Mat img,grey;
if(argc!= 2&&!(img = imread(argv [1],1))。data)
return -1;
cvtColor(img,gray,CV_BGR2GRAY);
// //平滑它,否则可能检测到很多假圆圈
GaussianBlur(灰色,灰色,尺寸(9,9),2,2);
vector< Vec3f>界;
HoughCircles(灰色,圆圈,CV_HOUGH_GRADIENT,
2,灰色 - >行/ 4,200,100);
for(size_t i = 0; i< circles.size(); i ++)
{
点中心(cvRound(circles [i] [0]),cvRound(圈[i ] [1]));
int radius = cvRound(circles [i] [2]);
//绘制圆心
circle(img,center,3,Scalar(0,255,0),-1,8,0);
//绘制圆形轮廓
circle(img,center,radius,Scalar(0,0,255),3,8,0);
}
namedWindow(circles,1);
imshow(circles,img);
返回0;
}

您试图将此C ++代码转换为Python,我认为?

  for(size_t i = 0; i  {
点中心(cvRound(circles [i] [0]),cvRound(circles [i] [1]));
int radius = cvRound(circles [i] [2]);
//绘制圆心
circle(img,center,3,Scalar(0,255,0),-1,8,0);
//绘制圆形轮廓
circle(img,center,radius,Scalar(0,0,255),3,8,0);
}

据我所知, CvMat 对象可迭代,就像列表一样:

 存储中的圆圈:
radius = circle [2]
center =(circle [0],circle [1])$ ​​b
$ b cv.Circle(im,center,radius,(0,0,255),3,8, 0)

我没有任何测试图片,所以不要误解我的意思。您的完整代码可能是:

  import cv 

def main():
im = cv.LoadImage('Proba.jpg')
gray = cv.CreateImage(cv.GetSize(im),8,1)
edges = cv.CreateImage(cv.GetSize(im), 8,1)

cv.CvtColor(im,gray,cv.CV_BGR2GRAY)
#cv.Canny(灰色,边缘,20,55,3)

storage = cv.CreateMat(im.width,1,cv.CV_32FC3)
cv.HoughCircles(edges,storage,cv.CV_HOUGH_GRADIENT,5,25,200,10)

我在xrange(storage.width - 1)中:
radius = storage [i,2]
center =(storage [i,0],storage [i,1])$ ​​b
$ b print(radius,center)

cv.Circle(im,center,radius,(0,0,255),3,8,0)

cv。 NamedWindow('Circles')
cv.ShowImage('Circles',im)
cv.WaitKey(0)

if __name__ =='__main__':
main()


I am trying to make a program which opens an image, scans it for circles/round shapes and returns the coordinates so that I can use the cv.Circle function to draw circles over the circle detected.

My question is: How do I get the coordinates/radii of the circles detected in an image using cv.HoughCircles() ?

Using this page, I found out how to detect the circles (which took me a lot of time to find out since I don't understand terms like threshold and the OpenCV documentation for Python is really poor, almost none). Unfortunately, on that page it didn't show how to extract the information of each circle detected from the CvMat created. How do I extract that information/is there some other way(eg. with MemoryStorage() ) ?

This is my code so far:

import cv, opencv

def main():


    im = cv.LoadImageM("Proba.jpg")

    gray = cv.CreateImage(cv.GetSize(im), 8, 1)
    edges = cv.CreateImage(cv.GetSize(im), 8, 1)

    cv.CvtColor(im, gray, cv.CV_BGR2GRAY)
    cv.Canny(gray, edges, 50, 200, 3)
    cv.Smooth(gray, gray, cv.CV_GAUSSIAN, 9, 9)

    storage = cv.CreateMat(im.rows, 1, cv.CV_32FC3)

    cv.HoughCircles(edges, storage, cv.CV_HOUGH_GRADIENT, 2, gray.height/4, 200, 100)
    # Now, supposing it found circles, how do I extract the information?
    print storage.r



if __name__ == '__main__':
    main()

Also, what value do the last two parameters of HoughCircles need to have in order for me to detect really small circles (like 3mm on the screen) ?

Thank you all for your time and effort trying to help me!

The image I'm working with is this:

解决方案

The last two parameters are what seem to be passed to cv.Canny(), which implies that cv.Canny() is called from within cv.HoughCircles(). I'm not too sure about that.

As for the sizes, it seems like the next two parameters (after 200, 100) default to 0, which might mean that all sizes are detected.

From the C++ example's source, I can also guess that you don't need to do a Canny edge detection:

#include <cv.h>
#include <highgui.h>
#include <math.h>

using namespace cv;

int main(int argc, char** argv)
{
    Mat img, gray;
    if( argc != 2 && !(img=imread(argv[1], 1)).data)
        return -1;
    cvtColor(img, gray, CV_BGR2GRAY);
    // smooth it, otherwise a lot of false circles may be detected
    GaussianBlur( gray, gray, Size(9, 9), 2, 2 );
    vector<Vec3f> circles;
    HoughCircles(gray, circles, CV_HOUGH_GRADIENT,
                 2, gray->rows/4, 200, 100 );
    for( size_t i = 0; i < circles.size(); i++ )
    {
         Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
         int radius = cvRound(circles[i][2]);
         // draw the circle center
         circle( img, center, 3, Scalar(0,255,0), -1, 8, 0 );
         // draw the circle outline
         circle( img, center, radius, Scalar(0,0,255), 3, 8, 0 );
    }
    namedWindow( "circles", 1 );
    imshow( "circles", img );
    return 0;
}

You're trying to convert this C++ code into Python, I assume?

for( size_t i = 0; i < circles.size(); i++ )
{
     Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
     int radius = cvRound(circles[i][2]);
     // draw the circle center
     circle( img, center, 3, Scalar(0,255,0), -1, 8, 0 );
     // draw the circle outline
     circle( img, center, radius, Scalar(0,0,255), 3, 8, 0 );
}

As far as I can tell, CvMat objects are iterable, just like a list:

for circle in storage:
  radius = circle[2]
  center = (circle[0], circle[1])

  cv.Circle(im, center, radius, (0, 0, 255), 3, 8, 0)

I don't have any test images, so don't take my word that this works. Your complete code would might be:

import cv

def main():
  im = cv.LoadImage('Proba.jpg')
  gray = cv.CreateImage(cv.GetSize(im), 8, 1)
  edges = cv.CreateImage(cv.GetSize(im), 8, 1)

  cv.CvtColor(im, gray, cv.CV_BGR2GRAY)
  #cv.Canny(gray, edges, 20, 55, 3)

  storage = cv.CreateMat(im.width, 1, cv.CV_32FC3)
  cv.HoughCircles(edges, storage, cv.CV_HOUGH_GRADIENT, 5, 25, 200, 10)

  for i in xrange(storage.width - 1):
    radius = storage[i, 2]
    center = (storage[i, 0], storage[i, 1])

    print (radius, center)

    cv.Circle(im, center, radius, (0, 0, 255), 3, 8, 0)

  cv.NamedWindow('Circles')
  cv.ShowImage('Circles', im)
  cv.WaitKey(0)

if __name__ == '__main__':
  main()

这篇关于Python和OpenCV。如何检测图像中的所有(填充)圆形/圆形对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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