0

Imagine that two kids drew some objects (look like dots) in two white papers, which are similar in size and dimension. I want to detect these objects, and count objects which are in a same x and y-axis, How can we count the similar objects? And measure the agreement between them? I found some similarity methods, but for these small objects did not work. You can see image examples here. A machine learning methods can be used here? Or a simple method of OpenCV ?

These two images are input (resized images of original images).

image1 image2

And these are my code, I tried this code from another similar post. The point is that the SSIM is not accurate in my case.

from skimage.metrics import structural_similarity
import numpy as np
import cv2
image1=cv2.imread("E:/image1.png")
image2=cv2.imread("E:/image2.png")

image1gray=cv2.cvtColor(image1, cv2.COLOR_BGR2GRAY)
image2gray=cv2.cvtColor(image2, cv2.COLOR_BGR2GRAY)

# Compute SSIM between the two images
(score, diff) = structural_similarity(image1gray, image2gray, full=True)
print("Image Similarity: {:.4f}%".format(score * 100))

# The diff image contains the actual image differences between the two images
# and is represented as a floating point data type in the range [0,1] 
# so we must convert the array to 8-bit unsigned integers in the range
# [0,255] before we can use it with OpenCV
diff = (diff * 255).astype("uint8")
diff_box = cv2.merge([diff, diff, diff])

# Threshold the difference image, followed by finding contours to
# obtain the regions of the two input images that differ
thresh = cv2.threshold(diff, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1]
contours = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = contours[0] if len(contours) == 2 else contours[1]

mask = np.zeros(image1.shape, dtype='uint8')
filled_image2 = image2.copy()
filled_image1=image1.copy()

for c in contours:
    area = cv2.contourArea(c)
    if area > 40:
        x,y,w,h = cv2.boundingRect(c)
        cv2.rectangle(image1, (x, y), (x + w, y + h), (36,255,12), 2)
        cv2.rectangle(image2, (x, y), (x + w, y + h), (36,255,12), 2)
        cv2.rectangle(diff_box, (x, y), (x + w, y + h), (36,255,12), 2)
        cv2.drawContours(mask, [c], 0, (255,255,255), -1)
        cv2.drawContours(filled_image2, [c], 0, (0,255,0), -1)
        cv2.drawContours(filled_image1, [c], 0, (0,255,0), -1)

cv2.imwrite('E:/Outout/image11.png', image1)
cv2.imwrite('E:/Outout/image22.png', image2)
cv2.imwrite('E:/Outout/diff_img.png', diff)
cv2.imwrite('E:/Outout/diff_box.png', diff_box)
cv2.imwrite('E:/Outout/mask.png', mask)
cv2.imwrite('E:/Outout/filled image2.png', filled_image2)

You can see the output that are not accurate as well. image11 image22 diff_img diff_box mask filled image2

What I want is a contour for each spot in the image, but by using this method I can get some patterns of dots in a contour.

Bilal
  • 3,191
  • 4
  • 21
  • 49
diana
  • 1
  • 2
  • Didn't Carl Sagan suggest something similar: printing dots on paper form all white to all black to print all knowlwdge... – Solar Mike Dec 19 '22 at 14:07
  • A bit more detailed explanation of what you exactly want would help. – Rajat Shenoi Dec 19 '22 at 14:07
  • Those images doesn't have the same resolutions. Is that intentional too? – jvx8ss Dec 19 '22 at 14:25
  • My project is about measuring agreement between two persons in detecting objects in a same image. On one RGB image, two persons detect objects, When I export the annotations, it would be like a white image which some dots on it. – diana Dec 19 '22 at 14:27
  • @jvx8ss I put these images as an example, but in real two images are bmp file and very large. – diana Dec 19 '22 at 14:27
  • You should attach the original images, that can make a big difference in the end result – jvx8ss Dec 19 '22 at 14:29
  • the original images are huge. more than 4 GB. – diana Dec 19 '22 at 14:30
  • That makes it not reproduce-able. But you could try to use `cv2.findContours()` and `cv2.boundingRect()` to get the dots positions. You will need to convert the images to gray and `cv2.bitwise_not()` them – jvx8ss Dec 19 '22 at 14:31
  • @jvx8ss I used 'cv2.findContours()' , but the result is not good. it detect two, three or more dots together and draw countours. – diana Dec 19 '22 at 14:48
  • @diana I think you should crop a small portion of those images and attach here. – jvx8ss Dec 19 '22 at 14:50
  • Unfortunately, I'm restricted to share more image and codes. small portion of images are attached in the question. – diana Dec 19 '22 at 15:12
  • To get only points that are set in both pictures, use a bit-operation: cv.bitwise_and(). Also: if your image really is binary (only two colors), they should compress really well. Try saving as TIFF (LZW on) or PNG instead of BMP. – nick Dec 19 '22 at 15:57
  • @jvx8ss I edited my post, now there is two resized images and outputs. – diana Dec 19 '22 at 17:43

0 Answers0