OpenCVの(Hough)Circle検出を使用して円を検出しようとしています。黒の背景に黒丸を作成し、パラメータを試して、ぼかしなどを使用しましたが、何も検出できません。
どんなアイデア、提案なども素晴らしいでしょう、ありがとう!
私の現在のコードは次のようなものです:
import cv2
import numpy as np
"""
params = dict(dp=1,
minDist=1,
circles=None,
param1=300,
param2=290,
minRadius=1,
maxRadius=100)
"""
img = np.ones((200,250,3), dtype=np.uint8)
for i in range(50, 80, 1):
for j in range(40, 70, 1):
img[i][j]*=200
cv2.circle(img, (120,120), 20, (100,200,80), -1)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
canny = cv2.Canny(gray, 200, 300)
cv2.imshow('shjkgdh', canny)
gray = cv2.medianBlur(gray, 5)
circles = cv2.HoughCircles(gray, cv2.cv.CV_HOUGH_GRADIENT, 1, 20,
param1=100,
param2=30,
minRadius=0,
maxRadius=0)
print circles
circles = np.uint16(np.around(circles))
for i in circles[0,:]:
cv2.circle(img,(i[0],i[1]),i[2],(0,255,0),2)
cv2.circle(img,(i[0],i[1]),2,(0,0,255),3)
cv2.imshow('circles', img)
k = cv2.waitKey(0)
if k == 27:
cv2.destroyAllWindows()
コードは正常に機能しています。問題はHoughCircles
しきい値パラメータにあります。
使用しているパラメータを理解してみましょう OpenCV Docs :
param1 –最初のメソッド固有のパラメーター。 CV_HOUGH_GRADIENTの場合、Canny()エッジ検出器に渡される2つのしきい値の高い方です(低い方のしきい値は2倍小さくなります)。
param2 –2番目のメソッド固有のパラメーター。 CV_HOUGH_GRADIENTの場合、これは検出段階での円の中心のアキュムレータしきい値です。小さいほど、誤った円が検出される可能性があります。大きいアキュムレータ値に対応する円が最初に返されます。
したがって、ご覧のとおり、内部的にHoughCircles関数はCanny Edge検出器を呼び出します。これは、関数で輪郭の代わりにグレー画像を使用できることを意味します。
次に、param1
を30に、param2
を15に減らして、次のコードで結果を確認します。
import cv2
import numpy as np
img = np.ones((200,250,3), dtype=np.uint8)
for i in range(50, 80, 1):
for j in range(40, 70, 1):
img[i][j]*=200
cv2.circle(img, (120,120), 20, (100,200,80), -1)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
circles = cv2.HoughCircles(gray, cv2.cv.CV_HOUGH_GRADIENT, 1, 20,
param1=30,
param2=15,
minRadius=0,
maxRadius=0)
print circles
circles = np.uint16(np.around(circles))
for i in circles[0,:]:
cv2.circle(img,(i[0],i[1]),i[2],(0,255,0),2)
cv2.circle(img,(i[0],i[1]),2,(0,0,255),3)
cv2.imshow('circles', img)
k = cv2.waitKey(0)
if k == 27:
cv2.destroyAllWindows()
HoughCirclesが明らかな円のピクセルパーフェクトソリューションを提供しない場合は、それを正しく使用していません
あなたの間違いは、ハイパーパラメータを自分で手動で調整しようとしていることです。それはうまくいきません。コンピューターにパラメーターを自動調整してもらいます。
import numpy as np
import argparse
import cv2
import signal
from functools import wraps
import errno
import os
import copy
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", required = True, help = "Path to the image")
args = vars(ap.parse_args())
image = cv2.imread(args["image"])
orig_image = np.copy(image)
output = image.copy()
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
cv2.imshow("gray", gray)
cv2.waitKey(0)
circles = None
minimum_circle_size = 100 #this is the range of possible circle in pixels you want to find
maximum_circle_size = 150 #maximum possible circle size you're willing to find in pixels
guess_dp = 1.0
number_of_circles_expected = 1 #we expect to find just one circle
breakout = False
max_guess_accumulator_array_threshold = 100 #minimum of 1, no maximum, (max 300?) the quantity of votes
#needed to qualify for a circle to be found.
circleLog = []
guess_accumulator_array_threshold = max_guess_accumulator_array_threshold
while guess_accumulator_array_threshold > 1 and breakout == False:
#start out with smallest resolution possible, to find the most precise circle, then creep bigger if none found
guess_dp = 1.0
print("resetting guess_dp:" + str(guess_dp))
while guess_dp < 9 and breakout == False:
guess_radius = maximum_circle_size
print("setting guess_radius: " + str(guess_radius))
print(circles is None)
while True:
#HoughCircles algorithm isn't strong enough to stand on its own if you don't
#know EXACTLY what radius the circle in the image is, (accurate to within 3 pixels)
#If you don't know radius, you need lots of guess and check and lots of post-processing
#verification. Luckily HoughCircles is pretty quick so we can brute force.
print("guessing radius: " + str(guess_radius) +
" and dp: " + str(guess_dp) + " vote threshold: " +
str(guess_accumulator_array_threshold))
circles = cv2.HoughCircles(gray,
cv2.cv.CV_HOUGH_GRADIENT,
dp=guess_dp, #resolution of accumulator array.
minDist=100, #number of pixels center of circles should be from each other, hardcode
param1=50,
param2=guess_accumulator_array_threshold,
minRadius=(guess_radius-3), #HoughCircles will look for circles at minimum this size
maxRadius=(guess_radius+3) #HoughCircles will look for circles at maximum this size
)
if circles is not None:
if len(circles[0]) == number_of_circles_expected:
print("len of circles: " + str(len(circles)))
circleLog.append(copy.copy(circles))
print("k1")
break
circles = None
guess_radius -= 5
if guess_radius < 40:
break;
guess_dp += 1.5
guess_accumulator_array_threshold -= 2
#Return the circleLog with the highest accumulator threshold
# ensure at least some circles were found
for cir in circleLog:
# convert the (x, y) coordinates and radius of the circles to integers
output = np.copy(orig_image)
if (len(cir) > 1):
print("FAIL before")
exit()
print(cir[0, :])
cir = np.round(cir[0, :]).astype("int")
for (x, y, r) in cir:
cv2.circle(output, (x, y), r, (0, 0, 255), 2)
cv2.rectangle(output, (x - 5, y - 5), (x + 5, y + 5), (0, 128, 255), -1)
cv2.imshow("output", np.hstack([orig_image, output]))
cv2.waitKey(0)
これに:
これが何をしているのかについての詳細は、以下を参照してください: https://stackoverflow.com/a/46500223/445131