import cv2
import numpy as np
# Read input images as Grayscale.
img1 = cv2.imread('image1.png', cv2.IMREAD_GRAYSCALE)
img2 = cv2.imread('image2.png', cv2.IMREAD_GRAYSCALE)
# Replace 255 with 100 (we want the sum img1+img2 not to overflow)
img1[img1 >= 128] = 100
img2[img2 >= 128] = 100
# Sum two images - in the sum, the value of overlapping parts of blobs is going to be 200
sum_img = img1 + img2
cv2.floodFill(sum_img, None, (0, 0), 0, loDiff=0, upDiff=0) # Remove the white frame.
cv2.imshow('sum_img before floodFill', sum_img) # Show image for testing.
# Find pixels with value 200 (the overlapping blobs).
thesh = cv2.threshold(sum_img, 199, 255, cv2.THRESH_BINARY)[1]
# Find contours (of overlapping blobs parts)
cnts = cv2.findContours(thesh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)[0]
# Iterate contours and fill the overlapping part, and the non-zero pixels around it (i.e with value 100) with zero.
for c in cnts:
area_tresh = 50
area = cv2.contourArea(c)
if area > area_tresh: # Ignore very tiny contours
x, y = tuple(c[0, 0]) # Get coordinates of first pixel in the contour
if sum_img[y, x] == 200:
cv2.floodFill(sum_img, None, (x, y), 0, loDiff=100, upDiff=0) # Setting loDiff=100 is set for filling pixels=100 (and pixels=200)
sum_img[sum_img == 200] = 0 # Remove the small remainders
#thesh = cv2.cvtColor(thesh, cv2.COLOR_GRAY2BGR) # Convert to BGR for testing (for drawing the contours)
#cv2.drawContours(thesh, cnts, -1, (0, 255, 0), 2) # Draw contours for testing
# Show images for testing.
cv2.imshow('thesh', thesh)
cv2.imshow('sum_img after floodFill', sum_img)
cv2.waitKey()
cv2.destroyAllWindows()
import cv2
import numpy as np
# Read input images as Grayscale.
img1 = cv2.imread('image1.png', cv2.IMREAD_GRAYSCALE)
img2 = cv2.imread('image2.png', cv2.IMREAD_GRAYSCALE)
# Replace 255 with 100 (we want the sum img1+img2 not to overflow)
img1[img1 >= 128] = 100
img2[img2 >= 128] = 100
# Dilate both images - assume close blobs are the same blob (two blobs are considered overlapped even if they are close but not tuching).
dilated_img1 = cv2.dilate(img1, np.ones((11, 11), np.uint8))
dilated_img2 = cv2.dilate(img2, np.ones((11, 11), np.uint8))
# Sum two images - in the sum, the value of overlapping parts of blobs is going to be 200
sum_img = dilated_img1 + dilated_img2
cv2.floodFill(sum_img, None, (0, 0), 0, loDiff=0, upDiff=0) # Remove the white frame.
#cv2.imshow('sum_img before floodFill', sum_img) # Show image for testing.
# Find pixels with value 200 (the overlapping blobs).
thesh = cv2.threshold(sum_img, 199, 255, cv2.THRESH_BINARY)[1]
# Find contours (of overlapping blobs parts)
cnts = cv2.findContours(thesh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)[0]
# Iterate contours and fill the overlapping part, and the non-zero pixels around it (i.e with value 100) with zero.
for c in cnts:
area_tresh = 0 # Optional
area = cv2.contourArea(c)
if area > area_tresh: # Ignore very tiny contours
x, y = tuple(c[0, 0]) # Get coordinates of first pixel in the contour
if sum_img[y, x] == 200:
cv2.floodFill(sum_img, None, (x, y), 0, loDiff=100, upDiff=0) # Setting loDiff=100 is set for filling pixels=100 (and pixels=200)
sum_img[sum_img == 200] = 0 # Remove the small remainders
sum_img[(img1 == 0) & (dilated_img1 == 100)] = 0 # Remove dilated pixels from dilated_img1
sum_img[(img2 == 0) & (dilated_img2 == 100)] = 0 # Remove dilated pixels from dilated_img2
sum_img[(img1 == 100) & (img2 == 0)] = 0 # Remove all the blobs that are only in first image (assume new blobs are "bored" only in image2)
# Visualization:
merged_img = cv2.merge((sum_img*2, img1*2, img2*2))
# The output image is img1, without the
output_image = img1.copy()
output_image[sum_img == 100] = 0
# Show images for testing.
cv2.imshow('sum_img', sum_img)
cv2.imshow('merged_img', merged_img)
cv2.waitKey()
cv2.destroyAllWindows()
1条答案
按热度按时间jhdbpxl91#
我们可以对两个图像进行求和,而不是使用OR、AND、XOR。
在对图像求和之前,将255个值替换为100(保持范围
uint8
[0,255])。在求和图像中,将有三个值:
0
-背景100
-非重叠区域200
-重叠面积我们可以假设具有与值
200
接触的值100
的像素属于相同的原始斑点。为了清除与接触像素(它们周围的100个)重叠的像素(200个),我们可以使用
cv2.floodFill
。清除重叠像素及其周围的像素后,剩下的像素(值为100)就是新的斑点。
使用
cv2.floodFill
清除像素的示例:设置
loDiff=100
用于用0
值填充像素=100(和像素=200)(200-loDiff
=100
,因此100
用零填充)。为了使解决方案更好,我们可以找到轮廓(像素=200),并且忽略微小轮廓。
代码示例:
注意事项:
如果两个相邻的斑点被认为是同一个斑点,我们可以首先放大图像(如果斑点可以“游泳”,我不知道)
输出
sum_img
(泛洪填充后):更新:
上面的解决方案找到了存在于图像1中而不存在于图像2中的斑点,以及存在于图像2中而不存在于图像1中的斑点。
在我们只想找到图像2中新的斑点的情况下,并且我们还假设在两个图像中接近的斑点是相同的斑点,我们可以添加以下阶段:
img1
和img2
(两个接近的斑点将重叠)。sum_img
中删除扩大的像素。sum_img
中删除所有只存在于img1
中(而不存在于img2
中)的blob。代码示例:
输出(
sum_img*2
):测试可视化(
merged_img
):img1
中img1
和img2
中img2
中,并且不太接近img1
中的斑点(我们正在寻找洋红色斑点)。