Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use ridge detection filter in opencv

I am trying to use ridge/valley filter with opencv-python. And I just checked the document in openCV's official website, which tells me to use

out = cv.ximgproc_RidgeDetectionFilter.getRidgeFilteredImage( _img[, out] ).

However, after trying, this function seems do not exist in cv2(python). Is there an alternative way to do this with openCV or any other available approach?

like image 372
zewen liu Avatar asked Feb 11 '18 03:02

zewen liu


3 Answers

Ridges are eigenvalues of matrix of second order derivate of image, also known as hessian matrix.

Using the above information, you can easily write a ridge detector using functionality provided by scikit-image

from skimage.features import hessian_matrix, hessian_matrix_eigvals
def detect_ridges(gray, sigma=3.0):
    hxx, hyy, hxy = hessian_matrix(gray, sigma)
    i1, i2 = hessian_matrix_eigvals(hxx, hxy, hyy)
    return i1, i2

Here, i1 returns local maxima ridges and i2 returns local minima ridges. You can tinker around with sigma values to get an appropriate solution. Example:

enter image description here

Actually, in Python/OpenCV, you can do something like this

image = cv2.imread('retina.tif')
ridge_filter = cv2.ximgproc.RidgeDetectionFilter_create()
ridges = ridge_filter.getRidgeFilteredImage(image)

Parameters for cv2.ximgproc.RidgeDetectionFilter_create include:

@param ddepth  Specifies output image depth. Defualt is CV_32FC1
@param dx Order of derivative x, default is 1 .   
@param dy  Order of derivative y, default is 1 .   
@param ksize Sobel kernel size , default is 3 .   
@param out_dtype Converted format for output, default is CV_8UC1 .   
@param scale Optional scale value for derivative values, default is 1 .   
@param delta  Optional bias added to output, default is 0 .   
@param borderType Pixel extrapolation  method, default is BORDER_DEFAULT

Source - https://docs.opencv.org/trunk/d4/d36/classcv_1_1ximgproc_1_1RidgeDetectionFilter.html

like image 123
Sagar B Hathwar Avatar answered Oct 20 '22 14:10

Sagar B Hathwar


Currently (scikit-image 1.14.1), the accepted answer does not work. Here is a version that does:

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

src_path = 'Fundus_photograph_of_normal_left_eye.jpg'

def detect_ridges(gray, sigma=1.0):
    H_elems = hessian_matrix(gray, sigma=sigma, order='rc')
    maxima_ridges, minima_ridges = hessian_matrix_eigvals(H_elems)
    return maxima_ridges, minima_ridges

def plot_images(*images):
    images = list(images)
    n = len(images)
    fig, ax = plt.subplots(ncols=n, sharey=True)
    for i, img in enumerate(images):
        ax[i].imshow(img, cmap='gray')
        ax[i].axis('off')
    plt.subplots_adjust(left=0.03, bottom=0.03, right=0.97, top=0.97)
    plt.show()

img = cv2.imread(src_path, 0) # 0 imports a grayscale
if img is None:
    raise(ValueError(f"Image didn\'t load. Check that '{src_path}' exists."))

a, b = detect_ridges(img, sigma=3.0)

plot_images(img, a, b)

fundus_fig

Source for image: https://en.wikipedia.org/wiki/Fundus_photography#/media/File:Fundus_photograph_of_normal_left_eye.jpg

like image 3
hhquark Avatar answered Oct 20 '22 16:10

hhquark


There is a version of the ridge detection algorithm based on "Steger, C., 1998. An unbiased detector of curvilinear structures. IEEE Transactions on Pattern Analysis and Machine Intelligence, 20(2), pp.113–125." paper.

It does not use openCV, and for that reason i hope not to be off topic, but you can modify the code according to your purposes

Here is the link: https://gitlab.gwdg.de/sphire/ridge_detection

You can install it directly via pip https://pypi.org/project/ridge-detection/

like image 2
buon_lu Avatar answered Oct 20 '22 16:10

buon_lu