使用opencv检测类似Omega的额头皱纹

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

我正在开展一个项目,检测额头上的欧米茄样皱纹(抑郁症的诊断特征)。根据这篇论文,我发现 Hessian 过滤器是检测皱纹的好方法:

Yap, M. H.、Alarifi, J.、Ng, C.、Batool, N. 和 Walker, K. (2019)。自动面部皱纹注释器。计算机科学讲义(第 676-680 页)。 https://doi.org/10.1007/978-3-030-11018-5_5

我使用了 skimage 的 hessian 过滤器,虽然根据 this 不是最佳选择,但对我来说已经足够了。

我按顺序应用了以下内容:

  1. 高斯模糊。
  2. Hessian 滤波器。
  3. 关闭操作。

这是我的代码:

image = io.imread("1.jpg", as_gray=True)
image = cv2.GaussianBlur(image, (5,5), 0)
hessian_image = filters.hessian(image)

kernel = np.ones((5,5), np.uint8)
closing = cv2.morphologyEx(hessian_image, cv2.MORPH_CLOSE, kernel)

closing = np.array(np.divide(closing, np.amax(closing)), dtype=np.float64)
closing *= 255
closing = np.uint8(closing)

cv2.imshow("Closing", closing)
cv2.waitKey(0)

这是输入图像:

enter image description here

这是输出图像:

enter image description here

我无法使用模板匹配来检测类似欧米茄(或类似矩形)的形状,因为它们往往会因一张图像而异。你还有其他想法吗?

opencv computer-vision
1个回答
0
投票

也许您可以尝试使用连通分量来分析每种模式的结构。像这样的东西:

from skimage import measure, filters
import numpy as np

# segments by connected components
segmentation = measure.label(closing)

# finds areas of each connected component, omits background
areas = np.bincount(segmentation.ravel())[1:]
# finds threhsold to remove small components
t = filters.threshold_otsu(areas)
# finds connected component indexes, which areas greater than the threshold
indexes = np.where(areas > t)[0] + 1
# filters out small components
dominant_patterns = np.isin(segmentation, indexes) 

# this is applicable if the image well centered
# forehead center is approximately positioned at image center
# flip image by columns
dominant_patterns_flipped = np.flip(dominant_patterns, axis=1)
# finds intersection with flipped image
omega_like = dominant_patterns * dominant_patterns_flipped

这将为您提供以下图像:

enter image description here

现在我们可以使用以下函数按行和列对图像进行分析,以计算每行和每列的像素出现次数:

import numpy as np

def row_col_profiles(image):
    """
    Returns pixels occurances per row and column
    """
    rows, cols = np.indices((image.shape))
    
    row_lengths = np.bincount(rows.ravel())
    number_of_pixels_on_each_row = np.bincount(rows.ravel(), image.ravel())
    row_profile = number_of_pixels_on_each_row / row_lengths

    col_lengths = np.bincount(cols.ravel())
    number_of_pixels_on_each_col = np.bincount(cols.ravel(), image.ravel())
    col_profile = number_of_pixels_on_each_col / col_lengths

    return row_profile, col_profile

row_profile, col_profile = row_col_profiles(omega_like)

您可以像这样绘制该配置文件:

import matplotlib.pyplot as plt

fig, axes = plt.subplots(1,2, figsize=(10, 5))
axes[0].plot(row_profile)
axes[0].set_title("Horizontal Line Profile")
axes[0].set_xlabel("Row Index")
axes[0].set_ylabel("Bright Pixel Occurance")
axes[0].grid()
axes[1].plot(col_profile)
axes[1].set_title("Vertical Line Profile")
axes[1].set_xlabel("Column Index")
axes[1].set_ylabel("Bright Pixel Occurance")
axes[1].grid()

你会得到这样的结果: enter image description here

为了检查我们是否具有类似 omega 的模式,我们可以从该配置文件中获取一些阈值,例如 0.2,并且还要检查至少在垂直配置文件中处于相对相同水平的 2 个峰值(我使用了最大值的 -10%) ).

is_omega_like = row_profile.max()>=0.2 and col_profile.max()>=0.2 and len(np.where(col_profile>col_profile.max()*0.9)[0])>=2

您还可以尝试测量一些属性并在连接的组件上找到一些合理的阈值。请查看文档

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