Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to identify if the shapes of an image are symmetric or asymmetric using opencv - python?

I'm working on the extraction of image characteristics, in which I'm trying to identify if a certain image is symmetric or not. I am using opecv - python for the development of this work.

The code below is used to identify the center and the diameter of the region of interest. How could you know if this image is symmetrical or not?

import cv2
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.offsetbox import AnchoredText

IMG = '015'
thresh = cv2.imread(IMD+'.png',0)
_, contours,hierarchy = cv2.findContours(thresh,2,1)
print (len(contours))
cnt = contours

for i in range (len(cnt)):
    (x,y),radius = cv2.minEnclosingCircle(cnt[i])
    center = (int(x),int(y))
    radius = int(radius)
    cv2.circle(thresh,center,radius,(0,255,0),2)
    print ('Circle: ' + str(i) + ' - Center: ' + str(center) + ' - Radius: ' + str(radius))
plt.text(x-21, y+15, '+', fontsize=25, color = 'red')
plt.text(10, -10, 'Centro: '+str(center), fontsize=11, color = 'red')
plt.text(340, -10, 'Diametro: '+str((radius*2)/100)+'mm', fontsize=11,     color = 'red')
plt.Circle((10, -10), 7.2, color='blue')
plt.imshow(thresh, cmap='gray')
#plt.savefig(IMG+'-diam.png')
plt.show()

exit: enter image description here

In the case, I am wanting to classify if the spot I am analyzing is symmetric or not, the image below, visually it is noted that it is not symmetrical, while the first image of the above plot is symmetrical.

enter image description here

like image 428
Carlos Diego Avatar asked Dec 17 '22 20:12

Carlos Diego


2 Answers

I assume the variable thresh is a binary image.

In order to find symmetry for a non-uniform object, i suggest we compare the projection of the binary pixels in the X and Y axis. enter image description here

Then compare the 2 histogram via histogram comparing method such as correlation, chi-square or Bhattacharyya distances. ( Example in openCV : https://docs.opencv.org/2.4/doc/tutorials/imgproc/histograms/histogram_comparison/histogram_comparison.html)

G_X = cv2.reduce(thresh_square, 0 ,cv2.REDUCE_SUM)
G_Y = cv2.reduce(thresh_square, 1 ,cv2.REDUCE_SUM)

compare_val = cv2.compareHist(G_X ,G_Y ,cv2.HISTCMP_CORREL)

where thresh_square is a squared ROI centered at your binary blob. You need to have equal bins for G_X and G_Y to make meaningful comparison.

A higher correlation value should correspond to a symmetric object while a lower correlation value will corresponds to an asymmetrical object.

Run this code to a few of the symmetric and asymmetric examples and check the compare_val value. You should be able to find a threshold to separate the two.

like image 82
yapws87 Avatar answered Feb 22 '23 22:02

yapws87


Here is how I would go about this problem:

  1. Measure the distance from the center for each radii
  2. Split the measurements into two groups (0 to 180, 180 to 360)
  3. Get the average of the two groups and compare to see if they are equal within a margin of error.
  4. Rotate the splitting of the groups by 1 degree and try again until you get to 179 degrees
  5. check if any splitting returned are equal within the margin.

You may have to tweak the equality margin a while to find a range that is acceptably accurate.

Also, you may have to quorum check the rotations to see if x rotations are equal within margin then it is symmetrical.

you may also need to divide it into quadrants instead of half pending how many axis you want to check symmetry for.

like image 37
Seth Wahle Avatar answered Feb 22 '23 22:02

Seth Wahle