简体   繁体   中英

how to rotate mutiple rectangle coordinates around image center

When it comes to test a computer vision algorithm object detection, by rotating a test image one can detect some missed objects. By doing so, those detected object locations represented by (x,y) coordinates for each point in rectangles should be rotated back. The output of object detector is a Numpy array which contains eg 100 elements which each one has 4 pair points representing (x,y) coordinates of rectangles around detected objects ie a Numpy array with (100,8) shape. These objects were detected in rotated version of original images. Therefore, they have to be rotated back for visualization on original image. The original image has 5616x3744px resolution and so rotated version with eg 90 degree has 3744x5616px.

  • each row is like [x1,y1,x2,y2,x3,y3,x4,y4]

The question is how we can rotate all of these points in one line around image center which let's consider to be (2808,1872). When I run the following code, Python throws an error of ValueError: operands could not be broadcast together with shapes (1000,8) (2,) which makes sense. Speed is important in this case. So I am trying to avoid using for loops.

def Rotate2D(pts,cnt,degree):
    ang = math.radians(degree)
    '''pts = {} Rotates points(nx2) about center cnt(2) by angle ang(1) in radian'''
    return scipy.dot(pts-cnt,scipy.array([[scipy.cos(ang),scipy.sin(ang)],[-scipy.sin(ang),scipy.cos(ang)]]))+cnt

The problem is that you are trying to subtract "center" - a 2-element vector from a (100, 8) "array of coordinates". In what space? 8D? If so, the center also should be a list of 8 coordinates because a point in an 8D space is defined by providing its coordinates along each of the 8 axes.

Your code works if the array of coordinates is of shape (100, 2) .


If, when you say "100 elements which each one has 8 points representing (x,y) " you mean that each row in the array contains 4 (not 8) points (ie, pairs of x and y ) such as x1 , y1 , x2 , y2 , x3 , y3 , x4 , y4 , then the best way to deal with this is to reshape your pts array:

import numpy as np
def Rotate2D(pts, cnt, degree):
    ang = math.radians(degree)
    m = scipy.array([[scipy.cos(ang), scipy.sin(ang)],
                     [-scipy.sin(ang), scipy.cos(ang)]])
    rpts = scipy.dot(np.reshape(pts, (pts.size // 2, 2)) - cnt, m) + cnt
    rpts = np.reshape(rpts, pts.shape)

With the help of @AGNGazer, this question was answered. It is needed first to shift all of point to be around center: [0, 0] Let us consider a 2 objects rather than 100 ones for the sake of simplicity and 90 degree rotation.

old_coord = np.zeros((2,8))
old_coord [0] = [500, 500, 510, 500, 510, 510, 500, 510] # only filling one is enough to show the functionality.

shift to center using rotated image centers [1872,2808].

old_coord [:, list(range(0, 8, 2))] -= 1872
old_coord [:, list(range(1, 8, 2))] -= 2808

apply @AGNGazer 's function.

new_coord = Rotate2D(old_coord, [0, 0], 90)

shift to original image centere [1872, 2808]

new_coord [:, list(range(1, 8, 2))] += 1872
new_coord [:, list(range(0, 8, 2))] +=  2808
>>> new_coord
array([[5116.,  500., 5116.,  510., 5106.,  510., 5106.,  500.],
   [0.,  0., 0.,  0., 0.,  0., 0.,  0.]])

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM