【问题标题】:How to extract signature from an image (python script)?如何从图像中提取签名(python脚本)?
【发布时间】:2019-07-26 16:47:55
【问题描述】:

这是签名的示例图片:

如何在没有背景的情况下从此图像中获取签名,以便我可以将其粘贴到用户图像上。 如果背景不是白色怎么办?

我试过this,如何自定义不同的背景颜色?

【问题讨论】:

  • 到目前为止你尝试过什么代码?另外,你有没有做过任何研究或者对背景颜色有什么想法?
  • 给一个研究提示:google for 'opencv color segmentation'
  • 我刚刚编辑了关于我的方法的问题。

标签: python python-3.x image opencv python-imaging-library


【解决方案1】:

这是一个相当大的过程,主要是因为在不同大小的图像上添加图像需要很多步骤。我建议您检查下面代码中的所有中间步骤,以了解会发生什么。

我使用 HSV-colorspace 将签名与背景分开,如果签名或背景有其他颜色,这很容易适应。

我还没有找到@BahramdunAdil 使用的copyTo()-方法的python 绑定。您可以改用numpy.copyto() 功能。为此,我会将您推荐给this answer

我使用了一种不同的技术:将图像叠加到另一个图像之上,首先创建一个与签名大小相同的子图像。可以将签名添加到子图像中,然后将其放回主图像中。

或者,您可以采用阈值签名并使用@renedv1 的方法来保存 alpha 图像。为此使用sign_masked 图像。由于 HSV 范围,您可以创建更清晰的结果。 (注意:考虑到 sign_masked 的背景是黑色的)

结果:

代码:

    import numpy as np 
    import cv2
    # load image
    sign = cv2.imread("sign.jpg")
    bg_img = cv2.imread("green_area.jpg")

     # Convert BGR to HSV
    hsv = cv2.cvtColor(sign, cv2.COLOR_BGR2HSV)

    # define range of HSV-color of the signature
    lower_val = np.array([0,0,0])
    upper_val = np.array([179,255,150])

    # Threshold the HSV image to get a mask that holds the signature area
    mask = cv2.inRange(hsv, lower_val, upper_val)
    # create an opposite: a mask that holds the background area
    mask_inv= cv2.bitwise_not(mask)

    # create an image of the signature with background excluded
    sign_masked = cv2.bitwise_and(sign,sign,mask=mask)

    # get the dimensions of the signature
    height, width = sign.shape[:2]

    # create a subimage of the area where the signature needs to go
    placeToPutSign = bg_img[0:height,0:width]
    # exclude signature area 
    placeToPutSign_masked = cv2.bitwise_and(placeToPutSign, placeToPutSign, mask=mask_inv)
    # add signature to subimage
    placeToPutSign_joined = cv2.add(placeToPutSign_masked, sign_masked)

    # put subimage over main image
    bg_img[0:height,0:width] = placeToPutSign_joined

    # display image
    cv2.imshow("result", bg_img)

    cv2.waitKey(0)
    cv2.destroyAllWindows()

【讨论】:

  • 不是toCopy 而是copyTo()cv::copyTo(),C++ 中的所有函数都存在于Python 中,OpenCV 是用C++ 编写的,并为Python 提供了一个包装器。
  • 这确实是我所期望的。但是,我没有找到它的示例或文档。类似问题here 的答案也指出没有找到python 绑定。在那个答案中,numpy.copyto() 被使用。我将更新我的答案以澄清。如果您确实知道 opencv 中的绑定,我想知道 :)
  • 它不是numpy的函数,它是OpenCV的Mat数据类型的函数,你可以看到我用过什么对象的代码copyTo(),但是没有@987654335 @函数如你所说,你可能拼写错误,你仔细检查一下。
  • 是的,我知道它存在于 c++ 中。但是,对于 python,我似乎并不存在——即使你会期望它。我根据文档尝试了几件事,都给出了一个错误,说明它不存在。谷歌搜索“opencv python copyto”没有任何用处,只有指向 c++ 代码的链接。就像我说的,在我提到的答案中(从 2018 年 7 月开始)也指出没有找到绑定,所以不仅仅是我。这可能是 c++ / python 之间的(未知/不需要的?)差异。但是,我知道或者可以在 python 中找到copyto 的工作代码示例,请分享。
【解决方案2】:

我自己刚开始使用 Python,但我想我会尝试一个解决方案 - 想出了这个:

#!/usr/bin/python2

import cv2
import numpy as np

file_name = "/tmp/signature.jpg" # your signature image...

image = cv2.imread(file_name, 1)
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGBA)
# note: [R,G,B,255] below, so first 3 numbers [255,255,255] are your white 
# background pixels to be converted to RGBA setting of [0,0,0,0] (transparent)
image[np.all(image == [255, 255, 255, 255], axis=2)] = [0, 0, 0, 0]

cv2.imwrite("/tmp/signature-transparent.png", image)

这个脚本会抓取你的signature.jpg,从它找到的所有白色像素中创建一个透明的背景,然后将它写入signature.png。

看起来像这样:

但是它的边​​缘并不完全干净!有谁可以整理一下吗?

【讨论】:

    【解决方案3】:

    您应该考虑以下步骤:例如,假装它是您的用户图像:

    现在执行以下步骤:

    cv::namedWindow("result", cv::WINDOW_FREERATIO);
    cv::Mat signatureImg = cv::imread(R"(izrMq.jpg)");
    cv::Mat userImg = cv::imread(R"(user_image.jpg)");
    
    // make a mask
    cv::Mat mask;
    cv::cvtColor(signatureImg, mask, cv::COLOR_BGR2GRAY);
    cv::threshold(mask, mask, 150, 255, cv::THRESH_BINARY_INV);
    
    // now copy
    cv::Mat submat = userImg(cv::Rect(userImg.cols-signatureImg.cols, userImg.rows-signatureImg.rows, signatureImg.cols, signatureImg.rows));
    signatureImg.copyTo(submat, mask);
    
    cv::imshow("result", userImg);
    
    cv::waitKey();
    

    结果如下:

    希望对你有帮助!

    【讨论】:

    • 你能详细说明一下吗?我想为此编写一个 python 脚本。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-07-24
    • 1970-01-01
    • 2011-11-29
    • 2021-01-21
    • 1970-01-01
    • 2023-03-03
    • 1970-01-01
    相关资源
    最近更新 更多