使用OpenCV去除噪声并检测聚光灯中的圆形

huangapple go评论96阅读模式
英文:

Removing Noise and Detecting Circle in Spotlight Using OpenCV

问题

我一直在尝试使用OpenCV在聚光灯图像中检测圆圈,并且有各种我正在处理的图片,通常看起来像这四张图片之一:

使用OpenCV去除噪声并检测聚光灯中的圆形
使用OpenCV去除噪声并检测聚光灯中的圆形
使用OpenCV去除噪声并检测聚光灯中的圆形
使用OpenCV去除噪声并检测聚光灯中的圆形

经过一些图像处理(使用阈值、模糊化),我已经让图片看起来像这样:

使用OpenCV去除噪声并检测聚光灯中的圆形

然而,尝试使用HoughCircles函数,即使在玩弄了一段时间后似乎也无法正常工作。在使用HoughCircles时,我是不是忽略了什么,或者有没有比使用HoughCircles更好的方法来检测这些圆圈?

我的当前代码:

  1. import cv2 as cv
  2. import numpy as np
  3. img = cv.imread('image.jpg', cv.IMREAD_GRAYSCALE)
  4. img = cv.medianBlur(img,33)
  5. assert img is not None, "file could not be read, check with os.path.exists()"
  6. image = cv.adaptiveThreshold(img,255,cv.ADAPTIVE_THRESH_GAUSSIAN_C,
  7. cv.THRESH_BINARY,73,2)
  8. blur = cv.blur(image,(5,5))
  9. circles = cv.HoughCircles(blur,cv.HOUGH_GRADIENT,1,20,
  10. param1=50,param2=30,minRadius=30)
  11. circles = np.uint16(np.around(circles))
  12. for i in circles[0,:]:
  13. # draw the outer circle
  14. cv.circle(circles,(i[0],i[1]),i[2],(0,255,0),2)
  15. # draw the center of the circle
  16. cv.circle(circles,(i[0],i[1]),2,(0,0,255),3)
  17. cv.imshow('Objects Detected',blur)
  18. cv.waitKey(0)
英文:

I have been trying to detect circles in spotlight images using OpenCV and have a variety of pictures I am working with, generally looking something like these 4 images:

使用OpenCV去除噪声并检测聚光灯中的圆形
使用OpenCV去除噪声并检测聚光灯中的圆形
使用OpenCV去除噪声并检测聚光灯中的圆形
使用OpenCV去除噪声并检测聚光灯中的圆形

Following some image processing (using a threshold, blurring) I have gotten the images to look something like this:
使用OpenCV去除噪声并检测聚光灯中的圆形

However, trying to use the HoughCircles function, even after playing around with it for a while seems to not work. Is there something that I am glossing over while using Hough Cicles, or is there a better way to detect the circles than using HoughCircles?

My current code:

  1. import cv2 as cv
  2. import numpy as np
  3. img = cv.imread('image.jpg', cv.IMREAD_GRAYSCALE)
  4. img = cv.medianBlur(img,33)
  5. assert img is not None, "file could not be read, check with os.path.exists()"
  6. image = cv.adaptiveThreshold(img,255,cv.ADAPTIVE_THRESH_GAUSSIAN_C,\
  7. cv.THRESH_BINARY,73,2)
  8. blur = cv.blur(image,(5,5))
  9. circles = cv.HoughCircles(blur,cv.HOUGH_GRADIENT,1,20,
  10. param1=50,param2=30,minRadius=30)
  11. circles = np.uint16(np.around(circles))
  12. for i in circles[0,:]:
  13. # draw the outer circle
  14. cv.circle(circles,(i[0],i[1]),i[2],(0,255,0),2)
  15. # draw the center of the circle
  16. cv.circle(circles,(i[0],i[1]),2,(0,0,255),3)
  17. cv.imshow('Objects Detected',blur)
  18. cv.waitKey(0)

答案1

得分: 1

。结果的示例(注意:我使用了缩小尺寸的图像作为输入):

  • 阈值 = 167
  • 二值化结果以下图中的红色部分表示。

使用OpenCV去除噪声并检测聚光灯中的圆形

英文:

If you can't use fix threshold value, one of the simplest way is to try possible thresholds and choose the one that looks good.

In following sample code(C++), threshold value are tried in ascending order until the binalization result shape became "enoughly circle".

  1. //Circle fitting (Simple Least Square)
  2. void FitCircle( const std::vector<cv::Point> &Ps, cv::Point2f &C, float &r )
  3. {
  4. cv::Mat A( (int)Ps.size(), 3, CV_32F );
  5. cv::Mat B( (int)Ps.size(), 1, CV_32F );
  6. for( int i=0; i<Ps.size(); ++i )
  7. {
  8. const auto &P = Ps[i];
  9. A.at<float>( i,0 ) = (float)P.x;
  10. A.at<float>( i,1 ) = (float)P.y;
  11. A.at<float>( i,2 ) = 1.0f;
  12. B.at<float>( i ) = (float)(P.x*P.x + P.y*P.y);
  13. }
  14. cv::Mat X;
  15. cv::solve( A,B, X, cv::DECOMP_SVD );
  16. C.x = X.at<float>(0) * 0.5f;
  17. C.y = X.at<float>(1) * 0.5f;
  18. r = sqrt( X.at<float>(2) + C.x*C.x + C.y*C.y );
  19. }
  20. int main()
  21. {
  22. //Load image as gray-scale
  23. cv::Mat SrcImg = cv::imread( "SpotLight.png", cv::IMREAD_GRAYSCALE );
  24. if( SrcImg.empty() )return 0;
  25. cv::imshow( "Src", SrcImg );
  26. //Decide threshold value range [Min,Max) to try
  27. int Min=0, Max=255;
  28. {
  29. unsigned int Hist[256] = { 0 };
  30. for( int y=0; y<SrcImg.rows; ++y )
  31. {
  32. const unsigned char *p = SrcImg.ptr<unsigned char>(y);
  33. for( int x=0; x<SrcImg.cols; ++x, ++p )
  34. { ++Hist[ *p ]; }
  35. }
  36. {//Decide Min
  37. unsigned int Thresh = cvRound( SrcImg.rows * SrcImg.cols * 0.9 );
  38. unsigned int Sum = 0;
  39. while( Sum < Thresh ){ Sum += Hist[Min]; ++Min; }
  40. }
  41. //Decide Max
  42. while( Hist[Max]==0 ){ --Max; }
  43. }
  44. //Try for each threshold
  45. for( int Thresh=Min; Thresh<Max-1; ++Thresh )
  46. {
  47. //Binalize
  48. cv::Mat Bin;
  49. cv::threshold( SrcImg, Bin, Thresh, 255, cv::THRESH_BINARY );
  50. //Fit circle to largest contour
  51. //to evaluate how close the binalization result shape is to a circle
  52. cv::Point2f Center;
  53. float Radius;
  54. double FittingErr = 0;
  55. {
  56. //Extract Largest Contour
  57. std::vector< std::vector<cv::Point> > Conts;
  58. cv::findContours( Bin, Conts, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE );
  59. if( Conts.empty() )continue;
  60. int iLargestCont = 0;
  61. double MaxArea = 0;
  62. for( int i=0; i<Conts.size(); ++i )
  63. {
  64. double Area = cv::contourArea( Conts[i] );
  65. if( Area >= MaxArea ){ MaxArea = Area; iLargestCont = i; }
  66. }
  67. //Fit circle to the Contour and evaluate the fitting result
  68. FitCircle( Conts[iLargestCont], Center, Radius );
  69. for( const auto &P : Conts[iLargestCont] )
  70. {
  71. double dx = (double)P.x - Center.x;
  72. double dy = (double)P.y - Center.y;
  73. double e = fabs( sqrt(dx*dx + dy*dy) - Radius );
  74. FittingErr += e;
  75. }
  76. FittingErr /= Conts[iLargestCont].size();
  77. }
  78. //Check if Contour shape is "enoughly circle"
  79. if( FittingErr <= 0.5 )
  80. { //Show Result
  81. cv::Mat Show;
  82. std::cout << "Thresh = " << Thresh << std::endl;
  83. cv::cvtColor( SrcImg, Show, cv::COLOR_GRAY2BGR );
  84. Show.setTo( cv::Scalar(0,0,255), Bin );
  85. cv::imshow( "Result", Show );
  86. cv::waitKey();
  87. return 0;
  88. }
  89. }
  90. //
  91. std::cout << "(All try Failed)" << std::endl;
  92. return 0;
  93. }

Result of this sample (Note : I used shrinked size image to input) :

  • Threshold value = 167
  • Binalized Result is represented as Red color part in below.

使用OpenCV去除噪声并检测聚光灯中的圆形

huangapple
  • 本文由 发表于 2023年5月28日 11:03:11
  • 转载请务必保留本文链接:https://go.coder-hub.com/76349775.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定