如何将矩形/边界盒与图像一起旋转

发布于 2025-01-22 23:08:02 字数 1988 浏览 4 评论 0原文

我正在研究数据增强,并试图生成数据集中每个图像的合成版本。因此,我需要在图像中旋转图像,并与边界框一起旋转。

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

我正在使用pascal-voc注释格式,如图所示在这里。结果,我有以下信息。

x_min,y_min,x_max,y_max。图像的来源(我可以从图像大小中获取)

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

。 我从

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

I'm working on a data augmentation and im trying to generate synthetic version of every image in my dataset. So i need to rotate images and together with bounding boxes as well in the images.

im only going to rotate images by 90, 180, 270 degrees.

I'm using pascal-voc annotation format as shown here. As a result i have following info.

x_min, y_min, x_max, y_max. Origin of image(i can get it from image size)

i've searched a lot on it. But i couldnt find any solution for rotating bounding boxes( or rectangles)

i've tried something like this;
i've got this solution from here and tried to adapt it but didnt work.

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]

thanks.

EDIT:

I need to get this rotation together with image and bounding box.
First picture is original one, second one is rotated as 90 degree(counter-clockwise) and 3rd picture is rotated as -90 degree (counter-wise).
i tried to rotate manually on paint to be precise. So i got these results.

   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

Image Rotations; Original, 90 rotation, -90 rotation

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

飘过的浮云 2025-01-29 23:08:02

我找到了更简单的方式。

基于此剥离。我们可以在不使用这样的三角计算的情况下进行此计算:

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)

可以一遍又一遍地使用。并返回以Pascal-voc格式返回新的边界框。

i've found simpler way.
enter image description here

Base on this aproach. We can do this calculation without using trigonometric calculations like this:

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)

this can be used over and over again. And returns new bounding boxes values in Pascal-voc format.

情绪 2025-01-29 23:08:02

好的,也许这会有所帮助。假设您的矩形被存储为标记角的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()

OK, maybe this can help. Assuming your rectangle is stored as a set of 4 points marking the corners, this will do arbitrary rotation around another point. If you store the points in circular order, then plot will even look like rectangles. I'm not forcing the aspect ratio on the plot, so the rotated rectangle looks like it is skewed, but it's not.

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()

The code can be made simpler for the 90/180/270 cases, because no trigonometry is needed. It's just addition, subtraction, and swapping points. Here, the rectangle is just stored [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()
秋心╮凉 2025-01-29 23:08:02

我尝试了其他答案中提到的实现,但它们都不适合我。我必须将图像和边界框顺时针旋转90度,所以我做了这种方法,

def rotate90Deg( bndbox , image_width ):
    """
    image_width: Width of the image after clockwise rotation of 90 degrees
    """
    x_min,y_min,x_max,y_max = bndbox
    new_xmin = image_width - y_max # Reflection about center X-line
    new_ymin = x_min
    new_xmax = image_width - y_min # Reflection about center X-line
    new_ymax = x_max
    return [new_xmin, new_ymin,new_xmax,new_ymax]

用法

image = Image.open( "..." )
image = image.rotate( -90 )
new_bbox = rotate90Deg( bbox , image.width )

I tried the implementations mentioned in the other answers but none of them worked for me. I had to rotate the image and the bounding box clockwise by 90 degrees so I made this method,

def rotate90Deg( bndbox , image_width ):
    """
    image_width: Width of the image after clockwise rotation of 90 degrees
    """
    x_min,y_min,x_max,y_max = bndbox
    new_xmin = image_width - y_max # Reflection about center X-line
    new_ymin = x_min
    new_xmax = image_width - y_min # Reflection about center X-line
    new_ymax = x_max
    return [new_xmin, new_ymin,new_xmax,new_ymax]

Usage

image = Image.open( "..." )
image = image.rotate( -90 )
new_bbox = rotate90Deg( bbox , image.width )
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文