Richard Tran
Richard Tran

Reputation: 134

Detect wrinkle with Hessian matrix

Currently, I am trying to use Hessian matrix to detect wrinkles on the forehead. How could I remove out noises around these wrinkles? Below are my current code and result.

from skimage.feature import hessian_matrix, hessian_matrix_eigvals

image = cv2.imread("forehead.jpg")
gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
def detect_ridges(gray, sigma=1.0):
  H_elems = hessian_matrix(gray, sigma=sigma)
  maxima_ridge, minima_ridge = hessian_matrix_eigvals(H_elems)
  return maxima_ridge, minima_ridge

a, b = detect_ridges(gray, sigma=1.0)
fig, axs = plt.subplots(1, 2, figsize=(20, 20))
axs[0].imshow(gray, cmap="gray")
axs[1].imshow(a, cmap="gray")

forehead

ridge detection

Upvotes: 4

Views: 644

Answers (2)

Bilal
Bilal

Reputation: 3855

Simple thresholding and contour detection might give a preliminary results, however further processing is necessary for accurate detection:

enter image description here

#!/usr/bin/env python3

import cv2 
import numpy as np 
import matplotlib.pyplot as plt 
from skimage.feature import hessian_matrix, hessian_matrix_eigvals

im_path = "wrinkle.png"

img = cv2.imread(im_path)
  
# Convert the img to grayscale
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

def detect_ridges(gray, sigma=1.0):
  H_elems = hessian_matrix(gray, sigma=sigma, use_gaussian_derivatives=True)
  maxima_ridge, minima_ridge = hessian_matrix_eigvals(H_elems)
  return maxima_ridge, minima_ridge

a, b = detect_ridges(gray, sigma=1.0)
a = cv2.normalize(a, None, 255, 0, cv2.NORM_MINMAX, cv2.CV_8U)
a[a<np.mean(a)] = 0
a[a!=0]=255

k = 7
kernel = np.zeros((k, k) ,np.uint8)
kernel[k//2] = 1

a = cv2.morphologyEx(a, cv2.MORPH_OPEN, kernel)

mask = np.zeros_like(a)

# detect the contours on the binary image using cv2.CHAIN_APPROX_NONE
contours, hierarchy = cv2.findContours(image=a, mode=cv2.RETR_TREE, method=cv2.CHAIN_APPROX_NONE)

# draw contours on the original image
th_ = 15
for cnt in contours:
    if(cv2.contourArea(cnt)>th_):
        cv2.drawContours(image=mask, contours=cnt, contourIdx=-1, color=255, thickness=2, lineType=cv2.LINE_AA)
                
img[mask>0] = (0, 0, 255)

cv2.namedWindow("output", cv2.WINDOW_NORMAL)
cv2.imshow("output", img)
cv2.waitKey(0)

Upvotes: 1

Hari
Hari

Reputation: 1797

You could first pre-process the image with an edge preserving filter like bilateralFilter(), edgePreservingFilter() etc. A nice tutorial is here.

Edge preserving filters, cartooning an image etc are big topics with several interesting algorithms. Here is one well cited paper, which also has shared code: 100+ Times Faster Weighted Median Filter.

With the right settings, most likely, the wrinkles will remain while the texture-like patterns will be smoothed out.

Upvotes: 0

Related Questions