背景が白でシンプルな形の画像があります(各画像には1つの形があります)。特定の点(x、y)が形状の内側にあるかどうかを確認したいと思います。opencvでそれを行うにはどうすればよいですか?
3 に答える
関数を使用pointPolygonTest
します。これがチュートリアルです。
ポイントがシェイプの内側、外側、またはエッジ上にあるかどうかを判断するには、を使用してポイントが輪郭内にあるかどうかを確認できますcv2.pointPolygonTest()
。この関数は、、、またはを返し+1
、ポイントが輪郭の内側、外側、または輪郭上にあるかどうかをそれぞれ示します。形状の輪郭がすでにあると仮定すると、輪郭と点を関数に渡すだけで済みます。-1
0
(x,y)
result = cv2.pointPolygonTest(contour, (x,y), False)
関数では、3番目の引数はmeasureDist
です。の場合True
、画像内の点と輪郭の間の最短距離を見つけます。の場合False
、ポイントが輪郭の内側、外側、または輪郭上にあるかどうかを検出します。距離を見つけたくないので、measureDist
引数をに設定しますFalse
正方形の輪郭を見つけて、ポイントが輪郭内にあるかどうかを確認する例を次に示します。
テスト画像
輪郭を見つけてポイントをチェックした後の画像
結果
ポイント1:-1.0
ポイント2:1.0
ポイント3:0.0
したがって、point1は外側、point2は内側、point3は輪郭上にあります。
import cv2
image = cv2.imread('1.png')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
canny = cv2.Canny(gray, 120, 255, 1)
cnts = cv2.findContours(canny, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
point1 = (25, 50)
point2 = (200, 250)
point3 = (200, 350)
# Perform check if point is inside contour/shape
for c in cnts:
cv2.drawContours(image, [c], -1, (36, 255, 12), 2)
result1 = cv2.pointPolygonTest(c, point1, False)
result2 = cv2.pointPolygonTest(c, point2, False)
result3 = cv2.pointPolygonTest(c, point3, False)
# Draw points
cv2.circle(image, point1, 8, (100, 100, 255), -1)
cv2.putText(image, 'point1', (point1[0] -10, point1[1] -20), cv2.FONT_HERSHEY_SIMPLEX, 1.0, (0, 0, 0), lineType=cv2.LINE_AA)
cv2.circle(image, point2, 8, (200, 100, 55), -1)
cv2.putText(image, 'point2', (point2[0] -10, point2[1] -20), cv2.FONT_HERSHEY_SIMPLEX, 1.0, (0, 0, 0), lineType=cv2.LINE_AA)
cv2.circle(image, point3, 8, (150, 50, 155), -1)
cv2.putText(image, 'point3', (point3[0] -10, point3[1] -20), cv2.FONT_HERSHEY_SIMPLEX, 1.0, (0, 0, 0), lineType=cv2.LINE_AA)
print('point1:', result1)
print('point2:', result2)
print('point3:', result3)
cv2.imshow('image', image)
cv2.waitKey()
凸包内のすべてのポイントにアクセスしたい場合は、マスキングを行うことができます
これを解決するには、最初に凸包の白い色をcv2.fillPoly()で黒いフレームにペイントします。
- まず、フレームの形状に沿った黒いフレームを作成します
black_frame = np.zeros_like(your_frame).astype(np.uint8)
- 凸包を白く塗る
cv2.fillPoly(black_frame , [hull], (255, 255, 255))
- numpyブールインデックスを使用してマスクを作成します。True/False値が内部にあるマスクが生成されます。ピクセル値が白の場合はTrueになります。
mask = black_frame == 255
- フレームとマスクの間に製品を取得することでピクセル値にアクセスできます。Falseの場合、値は
targetROI = your_frame * mask
- マスクを使用してピクセルにアクセスします。
black_frame = np.zeros_like(your_frame).astype(np.uint8)
cv2.fillPoly(black_frame , [hull], (255, 255, 255))
mask = black_frame == 255
targetROI = your_frame * mask