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

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

说明

我有一个手指的图像(背景为绿色),并希望提取指甲作为特征。我的目标是用功能描述指甲的轮廓。但是我还没有尝试过的功能部分,我敢肯定我可以自己弄清楚。我很难拔出指甲,并希望得到您的帮助。您可以在帖子末尾找到图片。

到目前为止我所做的:

  1. 加载图像
  2. 调整图像大小以减少计算量
  3. 处理(模糊,去除绿色背景,转换成灰度)
  4. 从图像中提取指甲(如何?)

我尝试进行圆形检测或椭圆形检测。使用霍夫变换的圆检测无法识别指甲。椭圆检测也是如此(除了花了2分钟而且等待时间太长的事实)。现在我的问题是:有没有一种简单的方法可以解决问题并拔出指甲?

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

我的梦想是在指甲的开始处另外分开灰色/深色部分,但我没有做到这一点,因此放弃了这一部分。但是,如果您知道一种简便的方法,我很想听听。


重要的代码片段:

# imports

# helper functions
def remove_green(img):
    empty_img = np.zeros_like(img)
    RED, GREEN, BLUE = (2, 1, 0)
    reds = img[:, :, RED]
    greens = img[:, :, GREEN]
    blues = img[:, :, BLUE]
    # loop over the image, pixel by pixel
    tmpMask = (greens < 35) | (reds > greens) | (blues > greens)
    img[tmpMask == 0] = (0, 0, 0)  # remove background from original picture
    empty_img[tmpMask] = (255, 255, 255)  # mask with finger in white
    return img, empty_img

# main function
# load and process 
image = cv2.imread(imagePath, 1)  # load
image = cv2.resize(image, None, fx=0.3, fy=0.3)  # resize
image = cv2.GaussianBlur(image, (3, 3), 0)
no_green_image, mask_finger = remove_green(image)  # remove green
gray = cv2.cvtColor(no_green_image, cv2.COLOR_BGR2GRAY)  # gray scalEd
gray_mask_finger = cv2.cvtColor(mask_finger, cv2.COLOR_BGR2GRAY)

# refine edges
kernel = np.ones((5, 5), np.uint8)
gray_mask_finger = cv2.morphologyEx(gray_mask_finger, cv2.MORPH_GRADIENT, kernel)

detect_nail(gray_mask_finger)
# here I struggle

图像

[起始图像:

“起始图像”“>

已移除绿色并转换为灰色:

“已处理图像”“>

轮廓:

<< img src =“ https://image.soinside.com/eyJ1cmwiOiAiaHR0cHM6Ly9pLnN0YWNrLmltZ3VyLmNvbS82MG5lZy5wbmcifQ==” alt =“轮廓” >>>

说明我有一个手指的图像(背景为绿色),并希望提取指甲作为特征。我的目标是用功能描述指甲的轮廓。但是...

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

  • 对平滑的饱和度值应用阈值以分割ROI
  • 使用Sobel算子进行梯度计算,然后将阈值应用于边缘区域检测(具有高梯度值)
  • 轮廓检测和指甲区域分割
  • 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)
    

    逐步输出:enter image description here

    python image opencv edge-detection
    1个回答
    0
    投票

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

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