matlab 查找比较两个不同二进制图像的新斑点

0mkxixxg  于 2022-12-04  发布在  Matlab
关注(0)|答案(1)|浏览(180)

我在t=0和t=t时对同一样本拍摄了两张图像。在t时拍摄的图像中几乎没有新的斑点。我需要找到这些新的斑点(新斑点是在t=t时出现在新XY位置的斑点)。我想知道是否有人能帮忙?
我试过OR,AND,XOR,重建,但问题是两个图像之间相同的斑点并不完全相同。有时它们可能有大小差异,这使得问题变得复杂。
t=0

时的图像t=t

时的图像

jhdbpxl9

jhdbpxl91#

我们可以对两个图像进行求和,而不是使用OR、AND、XOR。
在对图像求和之前,将255个值替换为100(保持范围uint8 [0,255])。
在求和图像中,将有三个值:

  • 0-背景
  • 100-非重叠区域
  • 200-重叠面积

我们可以假设具有与值200接触的值100的像素属于相同的原始斑点。
为了清除与接触像素(它们周围的100个)重叠的像素(200个),我们可以使用cv2.floodFill
清除重叠像素及其周围的像素后,剩下的像素(值为100)就是新的斑点。
使用cv2.floodFill清除像素的示例:

if sum_img[y, x] == 200:
    cv2.floodFill(sum_img, None, (x, y), 0, loDiff=100, upDiff=0)

设置loDiff=100用于用0值填充像素=100(和像素=200)(200-loDiff = 100,因此100用零填充)。
为了使解决方案更好,我们可以找到轮廓(像素=200),并且忽略微小轮廓。
代码示例:

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()

注意事项:
如果两个相邻的斑点被认为是同一个斑点,我们可以首先放大图像(如果斑点可以“游泳”,我不知道)
输出sum_img(泛洪填充后):

更新:

上面的解决方案找到了存在于图像1中而不存在于图像2中的斑点,以及存在于图像2中而不存在于图像1中的斑点。
在我们只想找到图像2中新的斑点的情况下,并且我们还假设在两个图像中接近的斑点是相同的斑点,我们可以添加以下阶段:

  • 在求和之前扩大img1img2(两个接近的斑点将重叠)。
  • 从最后的sum_img中删除扩大的像素。
  • sum_img中删除所有只存在于img1中(而不存在于img2中)的blob。

代码示例:

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()

输出(sum_img*2):

测试可视化(merged_img):

  • 绿色-仅存在于img1
  • 黄色-存在于img1img2
  • 洋红-仅存在于img2中,并且不太接近img1中的斑点(我们正在寻找洋红色斑点)。

相关问题