我正在编写一个代码来自动纠正气泡表的 4 个选择。 我想在黑色矩形周围绘制bbox(由学生针对问题选择) 现在我使用
cv2.findContours
和 imutils.grab_contours
然后 four_point_transform
在我的气泡表中获得最大的矩形(它是我自己创建的自定义气泡表。围绕圆圈的大矩形将帮助我们更轻松地获得圆圈)
一切看起来都不错。但我想在检测并绘制每个问题答案周围的框后保存图像。我可以在变换后的图像中围绕圆圈绘制,但如何在原始图像中围绕圆圈绘制?
我认为我应该使用变换矩阵的逆并在原始图像中获取bbox。但我不知道这是否可能,以及如果可能的话该怎么做。
如果需要的话,这是我的代码:
def find_answer(dst,):
gray_dst = cv2.cvtColor(dst,cv2.COLOR_BGR2GRAY)
blurred_dst = cv2.GaussianBlur(gray_dst,(3,3),0)
edged_dst = cv2.Canny(blurred_dst,75,200)
black_threshold = np.sum(gray_dst[0:37,0:37])/(37*37)
cnts = cv2.findContours(edged_dst,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
cnts = imutils.grab_contours(cnts)
docCnt = None
if len(cnts):
cnts = sorted(cnts,key=cv2.contourArea,reverse=True)
for c in cnts:
peri = cv2.arcLength(c,True)
approx = cv2.approxPolyDP(c,0.02*peri,True)
if(len(approx))==4:
docCnt = approx
break
paper = four_point_transform(dst,docCnt.reshape(4,2))
warped = four_point_transform(gray_dst,docCnt.reshape(4,2))
thresh = cv2.threshold(warped,0,255,cv2.THRESH_BINARY_INV|cv2.THRESH_OTSU)[1]
cnts = cv2.findContours(thresh,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
cnts = imutils.grab_contours(cnts)
cnts = sorted(cnts,key=cv2.contourArea,reverse=True)
answers = {}
P=True
for i in range(len(q)):
w = q[i][0][2]
h = q[i][0][3]
area = w*h
li = []
for j in range(len(q[i])):
area = q[i][j][2]*q[i][j][3]
y1 = q[i][j][0]
x1 = q[i][j][1]
y2 = q[i][j][0] + q[i][j][2]
x2 = q[i][j][1] +q[i][j][3]
sum = np.sum(warped[x1:x2,y1:y2])
#print(sum)
#print(w,h)
if sum/area <black_threshold:
P = False
print('i:',i,'j:',j,'sum is:',sum)
print('thersh is:',area*188)
li.extend([4-j])
answers[i+1] = li
return answers
四点变换:
def four_point_transform(image, pts):
rect = order_points(pts)
(tl, tr, br, bl) = rect
# compute the width of the new image, which will be the
# maximum distance between bottom-right and bottom-left
# x-coordiates or the top-right and top-left x-coordinates
widthA = np.sqrt(((br[0] - bl[0]) ** 2) + ((br[1] - bl[1]) ** 2))
widthB = np.sqrt(((tr[0] - tl[0]) ** 2) + ((tr[1] - tl[1]) ** 2))
maxWidth = max(int(widthA), int(widthB))
# compute the height of the new image, which will be the
# maximum distance between the top-right and bottom-right
# y-coordinates or the top-left and bottom-left y-coordinates
heightA = np.sqrt(((tr[0] - br[0]) ** 2) + ((tr[1] - br[1]) ** 2))
heightB = np.sqrt(((tl[0] - bl[0]) ** 2) + ((tl[1] - bl[1]) ** 2))
maxHeight = max(int(heightA), int(heightB))
# now that we have the dimensions of the new image, construct
# the set of destination points to obtain a "birds eye view",
# (i.e. top-down view) of the image, again specifying points
# in the top-left, top-right, bottom-right, and bottom-left
# order
dst = np.array([
[0, 0],
[maxWidth - 1, 0],
[maxWidth - 1, maxHeight - 1],
[0, maxHeight - 1]], dtype = "float32")
# compute the perspective transform matrix and then apply it
M = cv2.getPerspectiveTransform(rect, dst)
warped = cv2.warpPerspective(image, M, (maxWidth, maxHeight))
# return the warped image
return warped
订单点数:
def order_points(pts):
rect = np.zeros((4, 2), dtype = "float32")
# the top-left point will have the smallest sum, whereas
# the bottom-right point will have the largest sum
s = pts.sum(axis = 1)
rect[0] = pts[np.argmin(s)]
rect[2] = pts[np.argmax(s)]
# now, compute the difference between the points, the
# top-right point will have the smallest difference,
# whereas the bottom-left will have the largest difference
diff = np.diff(pts, axis = 1)
rect[1] = pts[np.argmin(diff)]
rect[3] = pts[np.argmax(diff)]
# return the ordered coordinates
return rect
谢谢。
如此简单...只需找到原始形状和变形尺寸即可!将不同的 y 坐标添加到 bbox 的 y 中,并将 1/2 * 不同的 x 坐标添加到 bbox 的 x 中 ....尝试然后询问...