opencv库中houghcircle函数中的dp参数究竟是如何工作的?
Posted
技术标签:
【中文标题】opencv库中houghcircle函数中的dp参数究竟是如何工作的?【英文标题】:How exactly does the dp parameter in the houghcircle function in the opencv library work? 【发布时间】:2014-08-29 04:13:20 【问题描述】:我试图了解 .houghcircles()
函数,但我不完全了解 dp
如何影响结果。
抬头看http://docs.opencv.org/modules/imgproc/doc/feature_detection.html?highlight=houghcircles#houghcircles,上面写着:
dp
– 累加器分辨率与图像的反比 例如,如果dp=1
,则累加器具有相同的 分辨率作为输入图像。如果dp=2
,累加器有一半 宽高大。
假设您有一张 1000x1000 的图片。然后将 dp 设置为 3,所以累加器只能看到图像的 1/3?还是类似,图像大小保持不变但看到的像素数更少?即原始图像中的 3 个像素与累加器看到的 1 个像素相关,就像原始图像“模糊”一样?
通过了解其他参数然后摆弄dp
,我已经成功地准确检测出碗中红苹果的数量。
也许我对累加器的理解也不正确,因为两者是相关的?据我了解,它是一个区域被“命中”的次数,但我不确定它是如何计算“命中区域”的
我的代码需要一碗苹果,转换为 HSV,抓取微红色的色调,使用 bitWiseOr 将其转换为黑色或白色(不是灰度格式),然后执行一些 .erode()
/ .dilate()
以减少噪音,然后.houghcircles()
.
我生成的图像看起来像这样http://i.imgur.com/iGyr7TG.jpg
提前致谢。
【问题讨论】:
【参考方案1】:动词讲解, 示例 trahunt。
最好在交互式 GUI 演示中看到
一个可配置的 UI 面板允许通过移动几个滑块来调整参数
import sys
import cv2
import math
import numpy
from scipy.ndimage import label
pi_4 = 4*math.pi
def nothing_asCallback(x):
pass
def GUI_openCV_circles():
# --------------------------------------------------------------------------------GUI-<image>
frame = cv2.imread( "openCV_CircleDetection_IMG_LASSO_AREA.JPG" )
demo = frame[:800,:800,:]
# --------------------------------------------------------------------------------GUI-<window>-s
cv2.namedWindow( "DEMO.IN", cv2.cv.CV_WINDOW_AUTOSIZE )
cv2.namedWindow( "DEMO.Canny", cv2.cv.CV_WINDOW_AUTOSIZE )
cv2.namedWindow( "DEMO.Canny.Circles", cv2.cv.CV_WINDOW_AUTOSIZE )
# --------------------------------------------------------------------------------GUI-<state>-initial-value(s)
aKeyPRESSED = None # .init
aCanny_LoTreshold = 127
aCanny_LoTreshold_PREVIOUS = -1
aCanny_HiTreshold = 255
aCanny_HiTreshold_PREVIOUS = -1
aHough_dp = 1
aHough_dp_PREVIOUS = -1
aHough_minDistance = 10
aHough_minDistance_PREVIOUS = -1
aHough_param1_aCannyHiTreshold = 255
aHough_param1_aCannyHiTreshold_PREVIOUS = -1
aHough_param2_aCentreDetectTreshold = 20
aHough_param2_aCentreDetectTreshold_PREVIOUS = -1
aHough_minRadius = 10
aHough_minRadius_PREVIOUS = -1
aHough_maxRadius = 30
aHough_maxRadius_PREVIOUS = -1
# --------------------------------------------------------------------------------GUI-<ACTOR>-s
cv2.createTrackbar( "Lo_Treshold", "DEMO.Canny", aCanny_LoTreshold, 255, nothing_asCallback )
cv2.createTrackbar( "Hi_Treshold", "DEMO.Canny", aCanny_HiTreshold, 255, nothing_asCallback )
cv2.createTrackbar( "dp", "DEMO.Canny.Circles", aHough_dp, 255, nothing_asCallback )
cv2.createTrackbar( "minDistance", "DEMO.Canny.Circles", aHough_minDistance, 255, nothing_asCallback )
cv2.createTrackbar( "param1_HiTreshold", "DEMO.Canny.Circles", aHough_param1_aCannyHiTreshold, 255, nothing_asCallback )
cv2.createTrackbar( "param2_CentreDetect", "DEMO.Canny.Circles", aHough_param2_aCentreDetectTreshold, 255, nothing_asCallback )
cv2.createTrackbar( "minRadius", "DEMO.Canny.Circles", aHough_minRadius, 255, nothing_asCallback )
cv2.createTrackbar( "maxRadius", "DEMO.Canny.Circles", aHough_maxRadius, 255, nothing_asCallback )
cv2.imshow( "DEMO.IN", demo ) # static ...
# --------------------------------------------------------------------------------GUI-mainloop()
print " --------------------------------------------------------------------------- press [ESC] to exit "
while( True ):
# --------------------------------------------------------------------------------GUI-[ESCAPE]?
if aKeyPRESSED == 27:
break
# --------------------------------------------------------------------------------<vars>-DETECT-delta(s)
aCanny_LoTreshold = cv2.getTrackbarPos( "Lo_Treshold", "DEMO.Canny" )
aCanny_HiTreshold = cv2.getTrackbarPos( "Hi_Treshold", "DEMO.Canny" )
if ( aCanny_LoTreshold != aCanny_LoTreshold_PREVIOUS
or aCanny_HiTreshold != aCanny_HiTreshold_PREVIOUS
):
# --------------------------= FLAG
aCannyRefreshFLAG = True
# --------------------------= RE-SYNC
aCanny_LoTreshold_PREVIOUS = aCanny_LoTreshold
aCanny_HiTreshold_PREVIOUS = aCanny_HiTreshold
else:
# --------------------------= Un-FLAG
aCannyRefreshFLAG = False
aHough_dp = cv2.getTrackbarPos( "dp", "DEMO.Canny.Circles" )
aHough_minDistance = cv2.getTrackbarPos( "minDistance", "DEMO.Canny.Circles" )
aHough_param1_aCannyHiTreshold = cv2.getTrackbarPos( "param1_HiTreshold", "DEMO.Canny.Circles" )
aHough_param2_aCentreDetectTreshold = cv2.getTrackbarPos( "param2_CentreDetect","DEMO.Canny.Circles" )
aHough_minRadius = cv2.getTrackbarPos( "minRadius", "DEMO.Canny.Circles" )
aHough_maxRadius = cv2.getTrackbarPos( "maxRadius", "DEMO.Canny.Circles" )
if ( aHough_dp != aHough_dp_PREVIOUS
or aHough_minDistance != aHough_minDistance_PREVIOUS
or aHough_param1_aCannyHiTreshold != aHough_param1_aCannyHiTreshold_PREVIOUS
or aHough_param2_aCentreDetectTreshold != aHough_param2_aCentreDetectTreshold_PREVIOUS
or aHough_minRadius != aHough_minRadius_PREVIOUS
or aHough_maxRadius != aHough_maxRadius_PREVIOUS
):
# --------------------------= FLAG
aHoughRefreshFLAG = True
# ----------------------------------------------= RE-SYNC
aHough_dp_PREVIOUS = aHough_dp
aHough_minDistance_PREVIOUS = aHough_minDistance
aHough_param1_aCannyHiTreshold_PREVIOUS = aHough_param1_aCannyHiTreshold
aHough_param2_aCentreDetectTreshold_PREVIOUS = aHough_param2_aCentreDetectTreshold
aHough_minRadius_PREVIOUS = aHough_minRadius
aHough_maxRadius_PREVIOUS = aHough_maxRadius
else:
# --------------------------= Un-FLAG
aHoughRefreshFLAG = False
# --------------------------------------------------------------------------------REFRESH-process-pipe-line ( with recent <state> <vars> )
if ( aCannyRefreshFLAG ):
edges = cv2.Canny( demo, aCanny_LoTreshold,
aCanny_HiTreshold
)
# --------------------------------------------------------------------------------GUI-SHOW-Canny()-<edges>-onRefreshFLAG
cv2.imshow( "DEMO.Canny", edges )
pass
if ( aCannyRefreshFLAG or aHoughRefreshFLAG ):
circles = cv2.HoughCircles( edges, cv2.cv.CV_HOUGH_GRADIENT,
aHough_dp,
aHough_minDistance,
param1 = aHough_param1_aCannyHiTreshold,
param2 = aHough_param2_aCentreDetectTreshold,
minRadius = aHough_minRadius,
maxRadius = aHough_maxRadius
)
# --------------------------------------------------------------------------------GUI-SHOW-HoughCircles()-<edges>-onRefreshFLAG
demoWithCircles = cv2.cvtColor( demo, cv2.COLOR_BGR2RGB ) # .re-init <<< src
demoWithCircles = cv2.cvtColor( demoWithCircles, cv2.COLOR_RGB2BGR )
for aCircle in circles[0]:
cv2.circle( demoWithCircles, ( int( aCircle[0] ), int( aCircle[1] ) ),
aCircle[2],
(0,255,0),
1
)
pass
pass
cv2.imshow( "DEMO.Canny.Circles", demoWithCircles )
pass
# --------------------------------------------------------------------------------<vars>-UPDATE-<state>
# ref. above in .onRefreshFLAG RE-SYNC sections
# --------------------------------------------------------------------------------GUI-INPUT ? [ESCAPE]
aKeyPRESSED = cv2.waitKey(1) & 0xFF
pass
# --------------------------------------------------------------------------------GUI-<window>-s / DESTROY
cv2.destroyWindow( "DEMO.IN" )
cv2.destroyWindow( "DEMO.Canny" )
cv2.destroyWindow( "DEMO.Canny.Circles" )
# --------------------------------------------------------------------------------GUI-<window>-s
pass
def main():
GUI_openCV_circles()
return 0
if __name__ == '__main__':
main()
【讨论】:
我会接受这个答案,只是因为那句话——也因为它是唯一的答案,当我复制和粘贴这段代码时可能会告诉我 dp 是什么。 @PGT :o) 不错——看过一次,读过上百次。 OpenCV RefMan 说:dp
– 累加器分辨率与图像分辨率的反比。例如,如果 dp=1
,则累加器与输入图像具有相同的分辨率。如果 dp=2
,累加器的宽度和高度只有一半。
@user3666197 任何你知道的关于累加器的解释/细节的来源?以上是关于opencv库中houghcircle函数中的dp参数究竟是如何工作的?的主要内容,如果未能解决你的问题,请参考以下文章
#私藏项目实操分享#教你用OpenCV 和 Python实现圆物检测《-》HoughCircles
Python,OpenCV中的霍夫圆变换——cv2.HoughCircles()
HoughCircles 在 OpenCV 中无法正确检测圆
从 onCameraFrame、OpenCV、Android/Java 调用 HoughCircles() 方法时改变慢帧速率