我具有单个对象(标本)的图像,该图像是无法控制的背景色。该post的建议已解决了该问题。如果从垂直角度拍摄图像,则该代码可以很好地工作。
但是,我还有另一个问题。一些图像是从无法控制的角度拍摄的。我上面提到的帖子中的现有代码返回了意外结果。例如,给定原始图像
我修改该代码的想法是从外部轮廓制作遮罩,然后在原始遮罩和遮罩之间按位应用。但是我不知道如何从外部轮廓制作遮罩。我可以提出您的建议吗?
答案 0 :(得分:1)
您可以使用以下解决方案(尽管并不能很好地分离样本):
cv2.floodFill
确实将彩色背景替换为黑色背景。 floodFill
之后留下的一些不需要的伪像。 这是代码:
import numpy as np
import cv2
from scipy.interpolate import splprep, splev
orig_im = cv2.imread("specimen1.jpg")
im = orig_im.copy()
h, w = im.shape[0], im.shape[1]
# Seed points for floodFill (use two points at each corner for improving robustness)
seedPoints = ((0, 0), (10, 10), (w-1, 0), (w-1, 10), (0, h-1), (10, h-1), (w-1, h-1), (w-10, h-10))
# Fill background with black color
for seed in seedPoints:
cv2.floodFill(im, None, seedPoint=seed, newVal=(0, 0, 0), loDiff=(5, 5, 5), upDiff=(5, 5, 5))
# Use "close" morphological operation
im = cv2.morphologyEx(im, cv2.MORPH_OPEN, cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (10,10)));
#Convert to Grayscale, and then to binary image.
gray = cv2.cvtColor(im, cv2.COLOR_RGB2GRAY)
ret, thresh_gray = cv2.threshold(gray, 5, 255, cv2.THRESH_BINARY)
#Find contours
_, contours, _ = cv2.findContours(thresh_gray, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
c = max(contours, key=cv2.contourArea) # Get the largest contour
# Smooth contour
# https://agniva.me/scipy/2016/10/25/contour-smoothing.html
x,y = c.T
x = x.tolist()[0]
y = y.tolist()[0]
tck, u = splprep([x,y], u=None, s=1.0, per=1)
u_new = np.linspace(u.min(), u.max(), 20)
x_new, y_new = splev(u_new, tck, der=0)
res_array = [[[int(i[0]), int(i[1])]] for i in zip(x_new,y_new)]
smoothened = np.asarray(res_array, dtype=np.int32)
# For testing
test_im = orig_im.copy()
cv2.drawContours(test_im, [smoothened], 0, (0, 255, 0), 1)
# Build a mask
mask = np.zeros_like(thresh_gray)
cv2.drawContours(mask, [smoothened], -1, 255, -1)
# Apply mask
res = np.zeros_like(orig_im)
res[(mask > 0)] = orig_im[(mask > 0)]
# Show images for testing
cv2.imshow('test_im', test_im)
cv2.imshow('res', res)
cv2.imshow('mask', mask)
cv2.waitKey(0)
cv2.destroyAllWindows()
备注:
我认为解决方案不是很可靠。
您可能需要使用迭代方法(例如逐渐增加loDiff
和hiDiff
参数以匹配给定图像的最佳参数)。
结果:
第一个标本:
第二个标本:
第三标本: