在验证码图像上绘制轮廓

问题描述 投票:0回答:1

我试图在仅包含数字的图像中分离出数字。数字写得很紧密,轮廓建立在一组随机数字上,我无法将其分开。

原图:

1

我正在使用的代码:

gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)[1]
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(image=image, contours=contours, contourIdx=-1, color=(0, 255, 0), thickness=1, lineType=cv2.LINE_AA)

此代码生成的图像是:

2

我想将数字与此分开,但由于轮廓建立在一组数字上,我无法将它们分开。

python opencv captcha
1个回答
0
投票

在奥地利有一个非常好听的动词,“pfuschen”。从字面上看,就像做某事直到它起作用为止。 IE。对我的回答持保留态度。

正如 stateMachine 在他的评论中提到的,您可以通过使用阈值的列级总和来对数字进行分区。之后,您需要搜索液滴以识别分离情况。最后,检测并移动每个窗口的轮廓。

这是我到目前为止所拥有的:

im = cv2.imread("numbers.png") # read numbers
imRGB = cv2.cvtColor(im, cv2.COLOR_BGR2RGB) # convert to rgb for easy plotting
imGray = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY) # convert to gray
_, thresh = cv2.threshold(imGray, 127, 255, cv2.THRESH_BINARY_INV) # take inverse binary to have positive class as digits
columnWiseSum = np.sum(thresh > 0, axis=0) # sum each column
# the next two lines is to get the start of the first digit and the end of the last digit
firstNonZero = np.argmax(columnWiseSum != 0) # find last 0 in the first occurances of 0
lastNonZero = len(columnWiseSum) - np.argmax(columnWiseSum[::-1] != 0) - 1 # find first 0 in the last occurances of 0
peaks, _ = find_peaks(-columnWiseSum, height = -8) # get peaks, height was manually selected!!!!
peaks = np.insert(peaks, 0, firstNonZero) # insert start of first digit
peaks = np.append(peaks, lastNonZero) # insert end of last digit
# this is for plotting
fig,ax = plt.subplots(nrows = 2, ncols = 1, figsize=(4, 4))
ax[0].imshow(thresh)
ax[1].plot(-columnWiseSum)
ax[1].plot(peaks, -columnWiseSum[peaks], 'rx')
ax[1].set_xlim((0,120))
plt.tight_layout()

从上面的代码中,我得到以下结果:

正如您所注意到的,最大值(因为我否定了总和)出现在数字的分割处。因此,您可以定义一个可以在数字上绘制的窗口和轮廓,但是,首先您必须将其移动到其原始位置:

contouredImage = imRGB.copy() # copy image for contouring
for i in range(len(peaks)-1): # loop through peaks
    startIndex = peaks[i] # get start of digit
    endIndex = peaks[i+1] # and end of digit
    window = thresh[:, startIndex:endIndex] # define window where the digit is
    contours, hierarchy = cv2.findContours(window, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # get contour from window
    X,Y = np.array(contours).T # unpack contour to X and Y coordinates
    X += peaks[i] # add the location of the peak, i.e, shift the contour to the digit location on the original image
    modifiedContour = np.dstack((X, Y)) # re-do contour
    contouredImage = cv2.drawContours(contouredImage, modifiedContour, -1, (0, 255, 0), 1) # draw contour with red

由此我得到以下结果:

希望这对您有进一步的帮助,但我希望这个解决方案不是通用的,它会在某些时候(如果不是大多数情况下)失败。如果您有所发布示例的更多图片,请将其包含在您的帖子中。稍后我会检查代码是否可以以更好的方式应用。

© www.soinside.com 2019 - 2024. All rights reserved.