algorithmmathcomputer-vision360-degrees

How to find the centroid of pixels with same color in a 360° video?


Let I be a w x h frame from a 360° video stream. Let R be a red rectangle on that frame. R is smaller than the width of the image.

To compute the centroid of this rectangle we need to distinguish two cases:

Case 1 and 2 illustrated

As you can see there will be a problem to compute the centroid with classical methods in case 1. Please note that I only care about horizontal overlapping.

For the moment I am doing like this. First we detect the first point we find and use it as a reference, then we normalize dx which is the difference between a point and the reference and then we accumulate:

width = frame.width
rectangle_pixel = (255,0,0)
first_found_coord = (-1,-1)
centroid = (0,0)
centroid_count = 0

for pixel, coordinates in image:
  if(pixel != rectangle_pixel): 
    continue
  if(first_found_coord == (-1,-1)):
    first_found_coord = coordinates 
    centroid = coordinates
    continue

  dx = coordinates.x - first_found_coord.x
  if(dx > width/2):
    dx -= width
  else if(dx < - width/2):
    dx -= width

  centroid += (dx, coordinates.y)
  centroid_count++


final_centroid = centroid / centroid_count 

But it doesn't work as expected. Where is the problem, is there a faster solution ?


Solution

  • Since I'm computing the bounding boxes in the same scope, I do it in two steps. I first accumulate the coordinates of the pixels of interest. Then when I'm checking for overlapping bounding boxes, I subtract the with for each overlapping colors on the right half of the image. So I end up with a completed but slided rectangle.

    At the end I divide by the number of point found per color. If the result is negative I shift it by the size of width of the image.


    Alternatively:

    def get_centroid(image, interest_color):
        acc_x = 0
        acc_y = 0
        count = 0
        first_pixel = (0,0)
    
        for (x,y, color) in image:
          if(color not in interest_color):
            continue
    
          if(count == 0):
            first_pixel = (x,y)
    
          dx = x - first_pixel.x
    
          if(dx > L/2)
            dx -= L
          else if (dx < -L/2)
            dx += L
    
          acc_x += x
          acc_y += y
          count++
    
        non_scaled_result = acc_x / count, acc_y / count
        result = non_scaled_result + first_pixel
    
        return result