Reputation: 39
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
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
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