Pinid
Pinid

Reputation: 39

calculate a centroid with opencv

I have an image of multiple circles, inside the circles there are regions of hot spots, with high intensity (high pixel values) and areas with cold spots (low pixel values). I want to calculate the weighted centroid of each circle with OpenCV in Python. I'm using this piece of code:

im2, contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
for c in contours:
     # calculate moments for each contour
     M = cv2.moments(c)

     # calculate x,y coordinate of center
     if M["m00"] != 0:
         cX = int(M["m10"] / M["m00"])
         cY = int(M["m01"] / M["m00"])
      else:
         cX, cY = 0, 0

Ok, so this code simply takes binary image, extract all circles and finds the contour of each circle.

The thing is that I need to find the weighted centroid of an RGB/gray scale image (which considers the pixels intensity) and not the binary image. How can I do that?

Thank you!

Upvotes: 0

Views: 13173

Answers (2)

Sunny127
Sunny127

Reputation: 293

Some fixes to @yapws87 's answer:

import numpy as np
import cv2

# create a meshgrid for coordinate calculation
r,c = np.shape(ori_img)
r_ = np.linspace(0,r,r+1)
c_ = np.linspace(0,c,c+1)
x_m, y_m = np.meshgrid(c_, r_, sparse=False, indexing='xy')


im2, contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)


for c in contours:
     # Get the boundingbox
     x,y,w,h = cv2.boundingRect(c)

     # calculate x,y coordinate of center
     # Get the corresponding roi for calculation
     weights = ori_img[y:y+h,x:x+w]
     roi_grid_x = x_m[y:y+h,x:x+w]
     roi_grid_y = y_m[y:y+h,x:x+w]
     
     # get the weighted sum
     weighted_x = weights * roi_grid_x
     weighted_y = weights * roi_grid_y
     
     cx = np.sum(weighted_x) / np.sum(weights)
     cy = np.sum(weighted_y) / np.sum(weights)  

Upvotes: 1

yapws87
yapws87

Reputation: 1839

Here is a kind of a python pseudo code solution to your question. The code is designed to calculate the weighted center of the centroid. The intensity level of the image is used as weight in the calculation. Therefore, the higher the intensity the higher the weight.

To simplify the calculation process, we need to have meshgrid of x-coordinates and y-coordinates the size of the original image. The weighted average of x and y coordinated will give you the weighted centroids

import numpy as np
import cv2

# create a meshgrid for coordinate calculation
r,c = np.shape(ori_img)
r_ = np.linspace(0,r,r+1)
c_ = np.linspace(0,c,c+1)
x_m, y_m = np.meshgrid(c_, r_, sparse=False, indexing='ij')


im2, contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)


for c in contours:
     # Get the boundingbox
     x,y,w,h = cv2.boundingRect(c)

     # calculate x,y coordinate of center
     # Get the corresponding roi for calculation
     weights = ori_img[y:y+h,x:x+w]
     roi_grid_x = x_m[y:y+h,x:x+w]
     roi_grid_y = y_m[y:y+h,x:x+w]

     # get the weighted sum
     weighted_x = weights * roi_grid_x
     weighted_y = weights * roi_grid_y

     cx = np.sum(weighted_x) / np.sum(weights)
     cy = np.sum(roi_grid_y) / np.sum(weights)  

Upvotes: 0

Related Questions