web-dev-qa-db-ja.com

python opencv-ブロブ検出または円検出

円領域の検出に問題があります。 opencvのHoughCircles関数で試しました。ただし、画像はかなり似ていますが、関数を検出するためには、関数のパラメーターを異なるものにする必要があります。

私が試した別のアプローチは、すべてのピクセルを反復処理し、現在のピクセルが白かどうかを確認することでした。この場合、エリア内にブロブオブジェクトがあるかどうかを確認します(ブロブの中心までの距離がしきい値よりも小さい)。存在する場合、ピクセルをblobに追加し、存在しない場合は新しいblobを作成します。これも適切に機能しませんでした。

誰も私がこの仕事をする方法を知っていますか(90%検出)?サンプル画像と、サークルをマークした別の画像を添付しました。ありがとう!

example

example with arrows

UPDATE:これまでに助けてくれてありがとう!これは、等高線を取得し、エリアごとにフィルタリングするコードです。

im = cv2.imread('extract_blue.jpg')
imgray = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
im_gauss = cv2.GaussianBlur(imgray, (5, 5), 0)
ret, thresh = cv2.threshold(im_gauss, 127, 255, 0)
# get contours
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

contours_area = []
# calculate area and filter into new array
for con in contours:
    area = cv2.contourArea(con)
    if 1000 < area < 10000:
        contours_area.append(con)

これは非常にきれいに機能します。私はそれらを画像に描きました: contours_filtered_area

これは、円形度でフィルタリングした部分です。エリアでフィルタリングしたコードのすぐ下にあります。

contours_cirles = []

# check if contour is of circular shape
for con in contours_area:
    perimeter = cv2.arcLength(con, True)
    area = cv2.contourArea(con)
    if perimeter == 0:
        break
    circularity = 4*math.pi*(area/perimeter*perimeter)
    print circularity
    if 0.8 < circularity < 1.2:
        contours_cirles.append(con)

ただし、新しいリスト「contours_cirles」は空です。ループに「循環性」を印刷しましたが、値はすべて10 000〜100 000です。

UPDATE#2:不足している括弧を修正した後、現在動作しています!

contours_cirles = []

# check if contour is of circular shape
for con in contours_area:
    perimeter = cv2.arcLength(con, True)
    area = cv2.contourArea(con)
    if perimeter == 0:
        break
    circularity = 4*math.pi*(area/(perimeter*perimeter))
    print circularity
    if 0.7 < circularity < 1.2:
        contours_cirles.append(con)

どうもありがとう! :)

example_done

15
cmplx96

出発点として、次のことから始めることができます。

  • cv2.findContours()を使用して、指定された画像のすべての輪郭を見つけます
  • 各輪郭を繰り返します:
    • 等高線の面積が特定の範囲内にある場合、面積を計算します_70 < area < 150_。これにより、非常に小さい輪郭と大きい輪郭が除外されます。
    • 面積しきい値で輪郭をフィルタリングした後、輪郭のエッジの数を確認する必要があります。これは、cv2.approxPolyDP()を使用して実行できます。ここでサークルを検出するために、より高度な操作を適用できます。

このアプローチを実装し、今後作成するコードで質問を更新してください。

EDIT:@Mikiが示唆するように、circularity = 4pi(area/perimeter ^ 2)、0.9などのしきい値を決定して、形状が円形かどうかを確認します。完全な円の場合_circularity == 1_。必要に応じて、このしきい値を微調整できます。

arcLength を参照して輪郭の周囲を見つけ、 contourArea を使用して、円形度の計算に必要な輪郭の面積を取得できます。

5
ZdaR

Hough Transformationも画像内の円を検出し、希望の結果を得るためにしきい値で再生します(中心として赤い点がある緑の境界線で検出された円):

import cv2
import numpy as np

img = cv2.imread('rbv2g.jpg',0)
img = cv2.medianBlur(img,5)
cimg = cv2.cvtColor(img,cv2.COLOR_GRAY2BGR)

circles = cv2.HoughCircles(img,cv2.HOUGH_GRADIENT,1,10,
                            param1=50,param2=12,minRadius=0,maxRadius=20)

circles = np.uint16(np.around(circles))
for i in circles[0,:]:
    # draw the outer circle
    cv2.circle(cimg,(i[0],i[1]),i[2],(0,255,0),2)
    # draw the center of the circle
    cv2.circle(cimg,(i[0],i[1]),2,(0,0,255),3)

cv2.imshow('detected circles',cimg)
cv2.waitKey(0)
cv2.destroyAllWindows()

enter image description here

1
Sandipan Dey