我正在使用 OpenCV 检测图片中的一些裂缝。图片是 .TIF 文件,因为它来自显微镜。图片中有多处裂缝,正在检测中。但是边界连接到一些检测到的对象,将它们组合到一个非常大的检测到的对象/“裂缝”。
这是我的代码:
import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
src = cv.imread('cracks.TIF', cv.IMREAD_GRAYSCALE)
ret, th1 = cv.threshold(src, 95, 255, cv.THRESH_BINARY)
kernel = np.ones((2, 2), np.uint8)
closing = cv.morphologyEx(th1, cv.MORPH_CLOSE, kernel, iterations=2)
contours, hierarchy = cv.findContours(closing, cv.RETR_LIST, cv.CHAIN_APPROX_NONE)
overlay = src.copy()
cont = cv.drawContours(overlay, contours, -1, (0, 255, 0), 1)
titles = ["ORIGINAL", "THRESH_BINARY", "CLOSING" , "CONTOURS"]
images = [src, th1, closing, overlay]
for i in range(len(images)):
plt.subplot(2, 2, i+1), plt.imshow(images[i])
plt.title(titles[i])
plt.xticks([]), plt.yticks([])
plt.show()
这是输出:
当我放大裂缝检测时,脚本也会检测到边界并将其连接到从图像中切出的裂缝:
我上传了图片,所以你可以用我的脚本自己试试。
我尝试了一些不同的东西,但我无法让它正常工作。我想我遗漏了一些关于 OpenCV 如何运作但无法弄清楚的基本知识。
问题与边界无关,但与
findContours
找到白色轮廓(而不是黑色轮廓)的事实有关。
th1
几乎全是白色,所以它被检测为一个大轮廓。
将
cv.THRESH_BINARY
替换为cv.THRESH_BINARY_INV
以在th1
中反转黑白:
ret, th1 = cv.threshold(src, 95, 255, cv.THRESH_BINARY_INV)
用开代替闭形态运算(开相当于黑白颠倒时的闭):
opening = cv.morphologyEx(th1, cv.MORPH_OPEN, kernel, iterations=2)
代码示例:
import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
src = cv.imread('cracks.TIF', cv.IMREAD_GRAYSCALE)
ret, th1 = cv.threshold(src, 95, 255, cv.THRESH_BINARY_INV)
kernel = np.ones((2, 2), np.uint8)
#closing = cv.morphologyEx(th1, cv.MORPH_CLOSE, kernel, iterations=2)
opening = cv.morphologyEx(th1, cv.MORPH_OPEN, kernel, iterations=2) # Use opening instead of closing because of inverted black/white
contours, hierarchy = cv.findContours(opening, cv.RETR_LIST, cv.CHAIN_APPROX_NONE)
#overlay = src.copy()
overlay = cv.cvtColor(src, cv.COLOR_GRAY2BGR) # Convert to BGR before drawing contours
cont = cv.drawContours(overlay, contours, -1, (0, 255, 0), 1) # Draw contours with green color
titles = ["ORIGINAL", "THRESH_BINARY", "OPENING" , "CONTOURS"]
images = [src, th1, opening, overlay]
for i in range(len(images)):
plt.subplot(2, 2, i+1), plt.imshow(images[i])
plt.title(titles[i])
plt.xticks([]), plt.yticks([])
plt.show()