首页 > 解决方案 > 为简单环形目标上的弹孔分配分数

问题描述

我目前正在开展一个项目,以检测和评分简单环形目标上的弹孔。我现在拥有的代码根据轮廓的中心为孔分配一个分数。这是我正在使用的目标1

如果轮廓与较高区域的边界重叠,我希望它被分配更高的分数,无论中心在哪里。一个例子如下所示:

2] 2

我的程序的代码和输出如下所示,其中分数分别分配给中心而不是重叠边界:

尝试失败

from cv2 import cv2
import numpy as np
import imutils

def centroid(contour):
    M = cv2.moments(contour)
    cx = int(round(M['m10']/M['m00']))
    cy = int(round(M['m01']/M['m00']))
    centre = (cx, cy)
    return centre

def getScore(scoreboundaries, HoleDist): #function to assign a score to each hole

    score = 0

    if scoreboundaries[0]>HoleDist:
        score = 10
    for i in range(1, len(scoreboundaries)):
        if scoreboundaries[i-1]<=HoleDist<scoreboundaries[i]:
            score = len(scoreboundaries) - i
    return score


default = cv2.imread("3.jpg")
img = cv2.resize(default,(640,640))

hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
h,s,v = cv2.split(hsv)

v_mask = cv2.inRange(v, 0, 155)

cnts = cv2.findContours(v_mask.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = imutils.grab_contours(cnts)

for c in cnts:

    if cv2.contourArea(c) > 10000: 
        cv2.drawContours(img, [c], -1, (0, 255, 0), 2)
        area_max = cv2.contourArea(c) 
        
radius_max = np.sqrt(area_max / np.pi)
section_size = radius_max / 9

centre_v_mask = cv2.inRange(v, 215, 255)
cnts = cv2.findContours(centre_v_mask.copy(), cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
cnts = imutils.grab_contours(cnts)

for c in cnts:
    if cv2.contourArea(c) > 10:
        centre_coords = centroid(c)
       
h_mask = cv2.inRange(h, 0, 30)
h_mask = cv2.medianBlur(h_mask, 11)
cnts = cv2.findContours(h_mask.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = imutils.grab_contours(cnts)

holes = []
HoleDists = []


scoreboundaries = []
for i in range(1,10): #calculate other rings
    
    cv2.circle(img, centre_coords, int(i*(section_size)), (255, 0, 0), 1)
    scoreboundaries.append(int(i*(section_size)))

for c in cnts: #plot bullet holes

    if cv2.contourArea(c) > 1:
        x,y,w,h = cv2.boundingRect(c)
        pts =[(x, y), (x+w, y), (x, y+h), (x+w, y+h)]

        centre_holes = centroid(c)
        pts.append(centre_holes)

        pointscore = 0
        for pt in pts: 
            X = pt[0]
            Y = pt[1]
            
            HoleDist = np.sqrt((X-centre_coords[0])**2 + (Y - centre_coords[1])**2)
            HoleDists.append(HoleDist)
            score = getScore(scoreboundaries, HoleDist)

            if score>pointscore:
                pointScore = score

        cv2.circle(img, (centre_holes), 1, (0, 0, 255), -1)
        cv2.rectangle(img, (x,y),(x+w,y+h),(0,0,255),2)
        cv2.drawContours(img, [c], -1, (0, 255, 0), 1)
        

        cv2.putText(img, "Score: " + str(pointScore), (centre_holes[0] - 20, centre_holes[1] + 20),
        cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 2)

cv2.imshow('frame', img)
cv2.waitKey(0)

我想知道我哪里出错了。感谢所有帮助,谢谢。

标签: pythonopencvimage-processingcontour

解决方案


这是一个经典的 Python 错误。您在以下几行大写pointscore

pointScore = score
cv2.putText( img, "Score: " + str(pointScore) ....

所以你真的只是使用你看到的最后一个分数,因为pointscore总是0pointScore = score

这是修复了这两个错别字的图片。还要记住,OpenCV 轮廓只是一组连接在一起的点。如果需要,您可以使用相同的评分代码来迭代轮廓点。

在此处输入图像描述

如果你想换成使用轮廓点,这是一个很小的变化。

改变这个:

for pt in pts: 
    X = pt[0]
    Y = pt[1]

对此:

for pt in c:
    pt = pt[0] # contour points have an extra pair of brackets [[x,y]] 
    X = pt[0]
    Y = pt[1]

推荐阅读