【问题标题】:How to detect and extract signature from an image with OpenCV?使用 OpenCV 从图像中检测和提取签名
【发布时间】:2019-12-14 09:56:16
【问题描述】:

我正在导入附加的图像。导入图像后,我想删除水平线,检测签名然后提取它,在签名周围创建矩形,裁剪矩形并保存。

我正在努力将签名的整个区域识别为一个轮廓或一组轮廓。

我已经尝试过findcontour 以及各种检测签名区域的方法。请参考下面的代码。

Python 脚本:

imagePath

#read image
image = cv2.imread(imagePath,cv2.COLOR_BGR2RGB)

#Convert to greyscale
gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY) # grayscale

#Apply threshold
ret,thresh1 = cv2.threshold(gray, 0, 255,cv2.THRESH_OTSU|cv2.THRESH_BINARY_INV)

plt.imshow(thresh1,cmap = 'gray')


#preprocessing
rect_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (15,15))
dilation = cv2.dilate(thresh1, rect_kernel, iterations = 1)
plt.imshow(dilation,cmap = 'gray')


#Detect contours
contours, hierarchy = cv2.findContours(dilation, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
contours[0]

height, width, _ = image.shape
min_x, min_y = width, height
max_x = max_y = 0   
for contour, hier in zip(contours, hierarchy):
    (x,y,w,h) = cv2.boundingRect(contour)
    min_x, max_x = min(x, min_x), max(x+w, max_x)
    min_y, max_y = min(y, min_y), max(y+h, max_y)
    if w > 80 and h > 80:
        cv2.rectangle(frame, (x,y), (x+w,y+h), (255, 0, 0), 2)

if max_x - min_x > 0 and max_y - min_y > 0:
    fin=cv2.rectangle(image, (min_x, min_y), (max_x, max_y), (255, 0, 0), 2)



plt.imshow(fin)



final=cv2.drawContours(image, contours,-1,(0,0,255),6)

plt.imshow(final,cmap = 'gray')

最终目标是围绕整个签名创建矩形

试图概括另一张图片:

【问题讨论】:

    标签: python opencv image-processing computer-vision contour


    【解决方案1】:

    与移除水平线相比,执行颜色阈值可能更容易。这个想法是将签名隔离到掩码上,然后提取它。我们将图像转换为 HSV 格式,然后使用较低/较高的颜色阈值

    lower = np.array([90, 38, 0])
    upper = np.array([145, 255, 255])
    mask = cv2.inRange(image, lower, upper)
    

    面具

    为了检测签名,我们可以得到所有轮廓的边界框,然后使用 Numpy 找到左上角和右下角坐标

    boxes = []
    for c in cnts:
        (x, y, w, h) = cv2.boundingRect(c)
        boxes.append([x,y, x+w,y+h])
    
    boxes = np.asarray(boxes)
    left = np.min(boxes[:,0])
    top = np.min(boxes[:,1])
    right = np.max(boxes[:,2])
    bottom = np.max(boxes[:,3])
    

    现在我们有了边界框坐标,我们可以使用Numpy slicing to crop ROI

    ROI = result[top:bottom, left:right].copy()
    

    import numpy as np
    import cv2
    
    image = cv2.imread('new.png')
    result = image.copy()
    image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
    lower = np.array([90, 38, 0])
    upper = np.array([145, 255, 255])
    mask = cv2.inRange(image, lower, upper)
    
    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3,3))
    opening = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel, iterations=1)
    close = cv2.morphologyEx(opening, cv2.MORPH_CLOSE, kernel, iterations=2)
    
    cnts = cv2.findContours(close, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    cnts = cnts[0] if len(cnts) == 2 else cnts[1]
    
    boxes = []
    for c in cnts:
        (x, y, w, h) = cv2.boundingRect(c)
        boxes.append([x,y, x+w,y+h])
    
    boxes = np.asarray(boxes)
    left = np.min(boxes[:,0])
    top = np.min(boxes[:,1])
    right = np.max(boxes[:,2])
    bottom = np.max(boxes[:,3])
    
    result[close==0] = (255,255,255)
    ROI = result[top:bottom, left:right].copy()
    cv2.rectangle(result, (left,top), (right,bottom), (36, 255, 12), 2)
    
    cv2.imshow('result', result)
    cv2.imshow('ROI', ROI)
    cv2.imshow('close', close)
    cv2.imwrite('result.png', result)
    cv2.imwrite('ROI.png', ROI)
    cv2.waitKey()
    

    【讨论】:

    • 谢谢..一个查询..使用这种方法,我将无法仅提取签名..如何识别签名的起点和终点并仅裁剪图像的那部分?你能帮忙吗?
    • 检查更新,你可以得到所有轮廓的边界框,然后使用 Numpy 找到左上角和右下角的坐标。从那里,您可以提取 ROI
    • 我无法将此解决方案推广到其他一些图像。在另一张图像上尝试了相同的方法,但它不起作用。我已经上传了上面的图片。你能帮忙吗?
    • 尝试修改cv2.morphologyEx中的迭代次数。第二张图像中有更多噪点,因此您需要先腐蚀然后膨胀以清理小颗粒。将开始迭代设置为 4
    • 是的..尝试了一些形态转换,效果非常好...谢谢 nathancy..
    猜你喜欢
    • 2020-10-03
    • 2018-08-26
    • 1970-01-01
    • 1970-01-01
    • 2013-11-24
    • 2021-08-30
    • 1970-01-01
    • 1970-01-01
    • 2016-09-17
    相关资源
    最近更新 更多