使用 OpenCV 和 Python 提取楼层布局和阈值
Extract the floor layout and threshold with OpenCV and Python
我试过使用SSIM来提取两幅图像之间的差异,只得到建筑面积(image_a是原始的,image_b 有粉刷地板)。
预期的输出是阈值掩码。
我遇到的问题是 ssim 差异的阈值在我的情况下不起作用(示例如下所示)。
有人可以提供更好的阈值技术或理论吗?
from skimage.measure import compare_ssim
import cv2
...
image_a = cv2.imread(first)
image_b = cv2.imread(second)
gray_a = cv2.cvtColor(image_a, cv2.COLOR_BGR2GRAY)
gray_b = cv2.cvtColor(image_b, cv2.COLOR_BGR2GRAY)
_, diff = compare_ssim(gray_a, gray_b, full=True, gaussian_weights=True)
diff = (diff * 255).astype("uint8")
thresh = cv2.threshold(diff, 0, 255,
cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1]
contours = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = contours[0] if len(contours) == 2 else contours[1]
contour_sizes = [(cv2.contourArea(contour), contour) for contour in contours]
if len(contour_sizes) > 0:
largest_contour = max(contour_sizes, key=lambda x: x[0])[1]
x, y, w, h = cv2.boundingRect(largest_contour)
cv2.rectangle(image_a, (x, y), (x + w, y + h), (36, 255, 12), 2)
cv2.rectangle(image_b, (x, y), (x + w, y + h), (36, 255, 12), 2)
cv2.imwrite('image_a.jpg', image_a)
cv2.imwrite('image_b.jpg',image_b)
cv2.imwrite('thresh.jpg', thresh)
image_a 检测到最大轮廓
image_b 检测到最大轮廓
脱粒
通过对给定图像之间的差异的平均值进行阈值处理可以获得更好的结果。
def get_mask(img1, img2, thresh):
if img1.shape != img2.shape:
return
diff = cv2.absdiff(img1, img2)
diff = np.mean(diff, axis=2)
diff[diff <= thresh] = 0
diff[diff > thresh] = 255
mask = np.dstack([diff] * 3)
return mask
生成的蒙版中可能会出现伪影,可以通过应用 Morphological Transformations 来减少伪影。
我试过使用SSIM来提取两幅图像之间的差异,只得到建筑面积(image_a是原始的,image_b 有粉刷地板)。
预期的输出是阈值掩码。
我遇到的问题是 ssim 差异的阈值在我的情况下不起作用(示例如下所示)。
有人可以提供更好的阈值技术或理论吗?
from skimage.measure import compare_ssim
import cv2
...
image_a = cv2.imread(first)
image_b = cv2.imread(second)
gray_a = cv2.cvtColor(image_a, cv2.COLOR_BGR2GRAY)
gray_b = cv2.cvtColor(image_b, cv2.COLOR_BGR2GRAY)
_, diff = compare_ssim(gray_a, gray_b, full=True, gaussian_weights=True)
diff = (diff * 255).astype("uint8")
thresh = cv2.threshold(diff, 0, 255,
cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1]
contours = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = contours[0] if len(contours) == 2 else contours[1]
contour_sizes = [(cv2.contourArea(contour), contour) for contour in contours]
if len(contour_sizes) > 0:
largest_contour = max(contour_sizes, key=lambda x: x[0])[1]
x, y, w, h = cv2.boundingRect(largest_contour)
cv2.rectangle(image_a, (x, y), (x + w, y + h), (36, 255, 12), 2)
cv2.rectangle(image_b, (x, y), (x + w, y + h), (36, 255, 12), 2)
cv2.imwrite('image_a.jpg', image_a)
cv2.imwrite('image_b.jpg',image_b)
cv2.imwrite('thresh.jpg', thresh)
image_a 检测到最大轮廓
通过对给定图像之间的差异的平均值进行阈值处理可以获得更好的结果。
def get_mask(img1, img2, thresh):
if img1.shape != img2.shape:
return
diff = cv2.absdiff(img1, img2)
diff = np.mean(diff, axis=2)
diff[diff <= thresh] = 0
diff[diff > thresh] = 255
mask = np.dstack([diff] * 3)
return mask
生成的蒙版中可能会出现伪影,可以通过应用 Morphological Transformations 来减少伪影。