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?
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:
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
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)
Source for image: https://en.wikipedia.org/wiki/Fundus_photography#/media/File:Fundus_photograph_of_normal_left_eye.jpg
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/
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With