显微镜图像中线检测的帮助或建议

信息处理 图像处理 计算机视觉 过滤 边缘检测 霍夫变换
2022-02-04 13:24:10

我正在做一个个人项目,我想在显微镜图像中选择一些非常具体的线条。第一张图片是原始图像,第二张图片是我想检测的线条(黄色)的图像。不是直线是的,但确实是直线。

第一张图像,未检测到线条

黄色的兴趣线

现在,我为线检测制作了一个非常基本的代码,这种代码可以“有效”检测线,但在此过程中需要检测到很多不需要的线。查看带有另一个图像的示例(以及它下面的代码,在 Python 中,使用 OpenCV)。

我的代码的结果

import cv2 as cv
import numpy as np

#Load and normalize .tif image:
img = 'imagenes.tif'
img = cv.imread(img, 0)
img_scaled = cv.normalize(img,  np.zeros((800, 800)), 0, 255, cv.NORM_MINMAX)

#Resizing images:
pct = 30
w = int(img.shape[1] * pct / 100)
h = int(img.shape[0] * pct / 100)
dim = (w, h)
resized = cv.resize(img_scaled, dim, interpolation = cv.INTER_AREA)

# First stage: Gaussian blur.
gaussian = cv.GaussianBlur(resized,(5, 5),0)
# Second Stage: edge detection with Canny.
low_threshold = 90
high_threshold = 150
edges = cv.Canny(gaussian, low_threshold, high_threshold)
# Third stage: Hough Line transform.
rho = 1
theta = np.pi / 180
threshold = 15
minLineLenght = 15
maxLineGap = 15
myBlankLines = resized.copy()
lines = cv.HoughLinesP(edges, rho, theta, threshold, np.array([]),
                    minLineLenght, maxLineGap)
for line in lines:
    for x1,y1,x2,y2 in line:
        cv.line(myBlankLines,(x1,y1),(x2,y2),(255,0,0),5)


cv.imshow('image_resized', resized)
cv.imshow('Stage 1: Gaussian', gaussian)
cv.imshow('Stage 2: Edges', edges)
cv.imshow('Stage 3: Lines', myBlankLines)
cv.waitKey(0)
cv.destroyAllWindows()

现在。我不介意从零开始构建过滤器并避免使用 OpenCV 或任何其他图像处理/计算机视觉库。但我对我应该走的方向感到有点迷茫。我不确定是否:

  1. 做更多的预过滤。
  2. 调整霍夫线变换的参数。
  3. 可能与机器学习有关的其他东西。

你有什么建议?感谢您对这项有趣的任务提出的任何建议。

2个回答
  • 我用Median Blur代替Gaussian Blur, 用来Sobel Filter检测边缘,结果并不完美,但如果你调整好参数,你可以改进它们(而且它们很多!)

结果

#==================
# Import Libraries
#==================
import numpy as np
import cv2
import matplotlib.pyplot as plt

# Read Image
img = cv2.imread('1.png', 0)

# Median Blur
img = cv2.medianBlur(img, 3)

# Sobel filter for Edge detection
sobelx = cv2.Sobel(img,cv2.CV_64F,1,0,ksize=5)
sobely = cv2.Sobel(img,cv2.CV_64F,0,1,ksize=5)
sobel = np.sqrt(sobelx**2+sobely**2)

# Threshold Sobel to locate the lines
maxi = 0.30*sobel.max()
sobel[sobel<maxi] = 0

# Normalize
sobel = (255*sobel) / (sobel.max()-sobel.min())
sobel = sobel.astype('uint8')

# Hough Line transform.
rho = 1
theta = np.pi / 180
threshold = 15
minLineLenght = 18
maxLineGap = 13
myBlankLines = img.copy()
lines = cv2.HoughLinesP(sobel, rho, theta, threshold, np.array([]),
                    minLineLenght, maxLineGap)
for line in lines:
    for x1,y1,x2,y2 in line:
        cv2.line(myBlankLines,(x1,y1),(x2,y2),(255,0,0),1)

# Visualize Results
plt.imshow(myBlankLines, cmap='gray')
plt.axis('off')
plt.show()

我建议您不要使用自行开发的算法组合,而是在科学文献中查找现有解决方案。人们一遍又一遍地解决同样的问题,存在许多算法来检测线条。

一种非常流行的此类方法是 Frangi 的血管测量(AF Frangi 等人,“Multiscale Vessel Enhancement Filtering”,MICCAI 1998)。DIPlib一个实现(免责声明:我编写了这个实现)。

您可以使用pip install diplib. 此代码显示了如何使用它,包括第二步,其中(灰度)血管性测量被阈值:

import diplib as dip

img = dip.ImageRead('cfqZG.png')(1)

vesselness = dip.FrangiVesselness(img, sigmas=2.0, polarity='black')
out = dip.HysteresisThreshold(vesselness, 0.01, 0.15)

dip.Overlay(img, out).Show()

上面代码的输出

调整代码中的参数会给你更多或更少的行。

如果您需要更细的线条,只需添加一个细化步骤(dip.ConditionalThinning2D)。