如何将 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 格式的新边界框值。
我正在研究数据扩充,我正在尝试为我的数据集中的每个图像生成合成版本。所以我需要旋转图像以及图像中的边界框。
我只会将图像旋转 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 格式的新边界框值。