我正在研究图像的表面粗糙度,我使用了opencv的边缘检测功能,但它也检测了图像中的毛孔。有没有办法去毛孔?
我尝试调整阈值,但这只消除了侧面的边缘并使毛孔更加明显。我对 opencv 和此类问题还很陌生,所以大部分代码只是基于我在网上看到的示例。
import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
from scipy import ndimage
# need to add the scale to it
img = cv.imread('testim5.png', cv.IMREAD_GRAYSCALE)
blurred = ndimage.filters.gaussian_filter(img, 2, mode='nearest')
edges = cv.Canny(blurred,100,200) # adjusting thresholds will only eliminate the outside edges, not the pores
首先,您可以使用形态学操作来确保有趣的边连接起来。您可以阅读有关形态学运算的更多信息 OpenCV 网络:https://docs.opencv.org/4.x/d9/d61/tutorial_py_morphological_ops.html。
代码为:
import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
from scipy import ndimage
# Open the image
img = cv.imread('testim5.png', cv.IMREAD_GRAYSCALE)
# Note that `scipy.ndimage.filters.gaussian_filter` is deprecated, use `scipy.ndimage.gaussian_filter` instead
blurred = ndimage.gaussian_filter(img, 2, mode='nearest')
edges = cv.Canny(blurred,100,175)
# Apply morphological operation (closing) to the EDGES so they are connected
kernel = np.ones((5,3),np.uint8)
edges_closing = cv.morphologyEx(edges, cv.MORPH_CLOSE, kernel)
这样做的结果是垂直边缘不再那么不相交,如下图所示。
第二步是去除毛孔。可以将其视为删除小连接对象的问题,并且 @Soltius 在 如何使用 OpenCV 删除小连接对象中的解决方案效果很好。
您的情况的代码是:
# Remove smallest connected components
# To understand the following lines, look the answer of @Soltius in https://stackoverflow.com/questions/42798659/how-to-remove-small-connected-objects-using-opencv
nb_blobs, im_with_separated_blobs, stats, _ = cv.connectedComponentsWithStats(edges_closing)
sizes = stats[:, -1]
sizes = sizes[1:]
nb_blobs -= 1
# Minimum size of particles we want to keep (number of pixels).
# Here, it's a fixed value, but you can set it as you want.
min_size = 80
final_edges = np.zeros_like(im_with_separated_blobs)
for blob in range(nb_blobs):
if sizes[blob] >= min_size:
final_edges[im_with_separated_blobs == blob + 1] = 255
fig, axs = plt.subplots(ncols=3)
axs[0].imshow(img, cmap='gray')
axs[1].imshow(edges, cmap='gray')
axs[2].imshow(final_edges, cmap='gray')
axs[0].set_title('Original image')
axs[1].set_title('Original edges')
axs[2].set_title('New edges')
fig.tight_layout()
plt.show()
最终的边缘是: