如何将 rectangle/bounding 框与图像一起旋转

How to rotate a rectangle/bounding box together with an image

我正在研究数据扩充,我正在尝试为我的数据集中的每个图像生成合成版本。所以我需要旋转图像以及图像中的边界框。

我只会将图像旋转 90、180、270 度。

我正在使用如图所示的 pascal-voc 注释格式 here。结果我得到了以下信息。

x_min、y_min、x_max、y_max。图像来源(我可以从图像大小得到它)

我在上面搜索了很多。但是我找不到任何旋转边界框(或矩形)的解决方案

我试过这样的东西; 我从 here 那里得到了这个解决方案,并尝试对其进行调整但没有成功。

def rotateRect(bndbox, img_size, angle):
    angle = angle * math.pi/180 # conversion from degree to radian
    y_min, y_max, x_min, x_max = bndbox
    ox, oy = img_size[0]/2, img_size[1]/2 # coordinate of origin of image
    rect = [[x_min, y_min], [x_min, y_max],[x_max, y_min],[x_max, y_max]] # coordinates of points of corners of bounding box rectangle.
    nrp = [[0, 0], [0,0 ],[0,0],[0, 0]] #new rectangle position

    for i, pt in enumerate(rect):
        newPx = int(ox + math.cos(angle) * (pt[0] - ox) - math.sin(angle) * (pt[1] - oy)) # new coordinate of point x
        newPy = int(oy + math.sin(angle) * (pt[0] - ox) + math.cos(angle) * (pt[1] - oy))  # new coordinate of point y
        nrp[i] = newPx,newPy
        nx_min, ny_min, nx_max, ny_max = nrp[0][0], nrp[0][1], nrp[2][0], nrp[2][1] # new bounding boxes values. 
     return [ny_min, ny_max, nx_min, nx_max]

谢谢。

编辑:

我需要将这个旋转与图像和边界框结合起来。 第一张图片是原始图片,第二张图片旋转了 90 度(逆时针),第三张图片旋转了 -90 度(逆时针)。 为了准确起见,我试着在油漆上手动旋转。所以我得到了这些结果。

   original of img size:(640x480)
   rotation orj, 90, -90
            --------------
    x_min = 98,  345, 17
    y_min = 345, 218, 98
    x_max = 420, 462, 420
    y_max = 462, 540, 134

好的,也许这会有所帮助。假设您的矩形存储为一组标记角的 4 个点,这将围绕另一个点进行任意旋转。如果您以循环顺序存储点,则绘图甚至看起来像矩形。我没有在图上强制显示纵横比,因此旋转的矩形看起来像是倾斜的,但事实并非如此。

import math
import matplotlib.pyplot as plt

def rotatebox( rect, center, degrees ):
    rads = math.radians(degrees)

    newpts = []
    for pts in rect:
        diag_x = center[0] - pts[0]
        diag_y = center[1] - pts[1]

        # Rotate the diagonal from center to top left

        newdx = diag_x * math.cos(rads) - diag_y * math.sin(rads)
        newdy = diag_x * math.sin(rads) + diag_y * math.cos(rads)
        newpts.append( (center[0] + newdx, center[1] + newdy) )

    return newpts

# Return a set of X and Y for plotting.

def corners(rect):
    return [k[0] for k in rect]+[rect[0][0]],[k[1] for k in rect]+[rect[0][1]]

rect = [[50,50],[50,120],[150,120],[150,50]]
plt.plot( *corners(rect) )
rect = rotatebox( rect, (100,100), 135 )
plt.plot( *corners(rect) )
plt.show()

对于 90/180/270 的情况,代码可以变得更简单,因为不需要三角函数。这只是加法、减法和交换点。这里,矩形只是存储 [minx,miny,maxx,maxy].

import matplotlib.pyplot as plt

def rotaterectcw( rect, center ):
    x0 = rect[0] - center[0]
    y0 = rect[1] - center[1]
    x1 = rect[2] - center[0]
    y1 = rect[3] - center[1]
    return center[0]+y0, center[1]-x0, center[0]+y1, center[1]-x1

def corners(rect):
    x0, y0, x1, y1 = rect
    return [x0,x0,x1,x1,x0],[y0,y1,y1,y0,y0]

rect = (50,50,150,120)
plt.plot( *corners(rect) )
rect = rotaterectcw( rect, (60,100) )
plt.plot( *corners(rect) )
rect = rotaterectcw( rect, (60,100) )
plt.plot( *corners(rect) )
rect = rotaterectcw( rect, (60,100) )
plt.plot( *corners(rect) )
plt.show()

我找到了更简单的方法。

基于这个方法。我们可以在不使用像这样的三角函数计算的情况下进行此计算:

def rotate90Deg(bndbox, img_width): # just passing width of image is enough for 90 degree rotation.
   x_min,y_min,x_max,y_max = bndbox
   new_xmin = y_min
   new_ymin = img_width-x_max
   new_xmax = y_max
   new_ymax = img_width-x_min
   return [new_xmin, new_ymin,new_xmax,new_ymax]


rotate90Deg([98,345,420,462],640)

这个可以反复使用。 returns Pascal-voc 格式的新边界框值。