Python 如何用手指从图像中提取指甲?

Python 如何用手指从图像中提取指甲?,python,image,opencv,edge-detection,Python,Image,Opencv,Edge Detection,说明 我有一个手指的图像(绿色背景),想提取指甲作为特征。我的目标是用功能描述指甲的轮廓。然而,功能部分我还没有尝试过,我相信我可以自己弄明白。我挣扎着拔指甲,想得到你的帮助。你可以在文章的末尾找到图片 到目前为止我所做的: 加载图像 调整图像大小以减少计算工作量 处理它(模糊、去除绿色背景、转换为灰度 从图像中提取指甲(如何提取?) 我试着做一个圆检测或椭圆检测。使用hough变换的圆检测无法识别指甲。椭圆检测也是如此(除了需要2分钟,等待的时间太长)。现在我的问题是:有没有简单的方法解决问题

说明

我有一个手指的图像(绿色背景),想提取指甲作为特征。我的目标是用功能描述指甲的轮廓。然而,功能部分我还没有尝试过,我相信我可以自己弄明白。我挣扎着拔指甲,想得到你的帮助。你可以在文章的末尾找到图片

到目前为止我所做的:

  • 加载图像
  • 调整图像大小以减少计算工作量
  • 处理它(模糊、去除绿色背景、转换为灰度
  • 从图像中提取指甲(如何提取?)
  • 我试着做一个圆检测或椭圆检测。使用hough变换的圆检测无法识别指甲。椭圆检测也是如此(除了需要2分钟,等待的时间太长)。现在我的问题是:有没有简单的方法解决问题并提取指甲

    我还使用了边缘检测/轮廓检测来提取指甲,但是它太不准确,没有帮助

    我的梦想是在指甲开始时将灰色部分和深色部分分开,但我没有做到这一点,因此放弃了这一部分。不过,如果你知道一个简单的好方法,我很乐意听到


    重要的代码片段:

    #导入
    #辅助函数
    def清除_绿色(img):
    空\u img=np.类零(img)
    红、绿、蓝=(2、1、0)
    红色=img[:,:,红色]
    绿色=img[:,:,绿色]
    蓝色=img[:,:,蓝色]
    #逐像素在图像上循环
    tmpMask=(绿色<35)|(红色>绿色)|(蓝色>绿色)
    img[tmpMask==0]=(0,0,0)#从原始图片中删除背景
    空的_img[tmpMask]=(255、255、255)#手指为白色的遮罩
    返回img,空\u img
    #主要功能
    #负载与过程
    image=cv2.imread(imagePath,1)#加载
    图像=cv2。调整大小(图像,无,fx=0.3,fy=0.3)#调整大小
    图像=cv2.GaussianBlur(图像,(3,3,0)
    无绿色图像,遮罩手指=移除绿色(图像)#移除绿色
    灰色=cv2.CVT彩色(无绿色图像,cv2.COLOR颜色为灰色)#灰度
    gray\u mask\u finger=cv2.CVT颜色(mask\u finger,cv2.COLOR\u BGR2GRAY)
    #细化边
    内核=np.one((5,5),np.uint8)
    gray_mask_finger=cv2.morphologyEx(gray_mask_finger,cv2.MORPH_GRADIENT,内核)
    检测指甲(灰色面具、手指)
    #我在这里挣扎
    

    图像

    起始图像:

    删除绿色并转换为灰色:

    轮廓:


    考虑到语义/实例分割问题,我认为解决此问题的最佳方法可能是使用编码器-解码器(例如U-Net)类型的体系结构,因为使用基于传统图像处理的方法解决此问题非常具有挑战性。不过,我将尝试一下。 在我的方法中,我按照下面提到的步骤检测指甲区域(结果并不完美,但您可以对此进行改进):

    • 基于平滑饱和值的阈值分割感兴趣区域
    • 使用Sobel算子进行梯度计算,然后将阈值应用于边缘区域检测(具有高梯度值)
    • 轮廓检测与指甲区域分割
    逐步输出:

    通过该项目,它使用MobileNetV1 FPN SSD以阈值置信度检测图像中的指甲


    我担心你不会喜欢我的答案,但作为一名机器学习实践者,我认为最好的方法之一是手动注释多个拇指,并在其上训练分割神经网络。我想不出一种不会产生伪影或巨大缺陷的方法inaccuracies@Badogo使用MobileNetV1 FPN SSD进行指甲检测。。
    image = cv2.imread("finger.jpg")  # load image
    
    hsv_img = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)  # BGR to HSV conversion
    hsv_img = cv2.resize(hsv_img, (250, 250))
    
    img_s = hsv_img[:, :, 1]  # Extracting Saturation channel on which we will work
    
    img_s_blur = cv2.GaussianBlur(img_s, (7, 7), 0)  # smoothing before applying  threshold
    
    img_s_binary = cv2.threshold(img_s_blur, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]  # Thresholding to generate binary image (ROI detection)
    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
    img_s_binary = cv2.morphologyEx(img_s_binary, cv2.MORPH_OPEN, kernel, iterations=3)  # reduce some noise
    
    img_croped = cv2.bitwise_and(img_s, img_s_binary) * 2  # ROI only image extraction & contrast enhancement, you can crop this region 
    
    abs_grad_x = cv2.convertScaleAbs(cv2.Sobel(img_croped, cv2.CV_64F, 1, 0, ksize=3))
    abs_grad_y = cv2.convertScaleAbs(cv2.Sobel(img_croped, cv2.CV_64F, 0, 1, ksize=3))
    grad = cv2.addWeighted(abs_grad_x, .5, abs_grad_y, .5, 0)  # Gradient calculation
    grad = cv2.medianBlur(grad, 13)
    
    edges = cv2.threshold(grad, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]
    
    cnts = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)  # Contours Detection
    cnts = cnts[0] if len(cnts) == 2 else cnts[1]
    cnt = None
    max_area = 0
    for c in cnts:
        area = cv2.contourArea(c)
        if area > max_area:  # Filtering contour
            max_area = area
            cnt = c
    
    cv2.drawContours(hsv_img, [cnt], 0, (0, 255, 0), 3)