图片旋转后标注框对应问题(python opencv)

    今天看了看imgaug库关于仿射变化后图片上标注点和标注框的问题,感觉比较繁琐。因此还是使用自己写的代码来进行这些操作把。本篇讲一下旋转后标注框的变化:

1:图片旋转后尺寸分为原图像尺寸,对图像进行剪裁

2:图片旋转后尺寸从新计算,使用旋转后的尺寸进行仿射。

首先上个图:

    图上theta代表旋转角度,取值范围0-360,可为负数。坐标建立按照opencv的坐标系。旋转后的宽和高按照上面的公式进行计算即可。

    这个公式是仿射变化的公式,tx,ty是偏移量。

####input:  1.img type:numpy_array  2.angle  type:int 3.point type:numpy_array shape(None,8)
####output: 1.img 2.point 旋转后变化后的点坐标  shape(None,8) 8个坐标,顺序左上,右上,右下,左下
def rotation_point(img,angle=15,point=None,keep_size = False):
    if keep_size:
        cols = img.shape[1]
        rows = img.shape[0]
        M = cv2.getRotationMatrix2D((cols / 2, rows / 2), angle, 1)
        img = cv2.warpAffine(img, M, (cols, rows))
        a = M[:, :2]  ##a.shape (2,2)
        b = M[:, 2:]  ###b.shape(2,1)
        b = np.reshape(b,newshape=(1,2))
        a = np.transpose(a)
        point = np.reshape(point,newshape=(len(point)*4,2))
        point = np.dot(point,a)+b
        point = np.reshape(point,newshape=(len(point)/4,8))
        return img,point
    else:
        cols = img.shape[1]
        rows = img.shape[0]
        M = cv2.getRotationMatrix2D((cols / 2, rows / 2), angle, 1)

        heightNew = int(cols * fabs(sin(radians(angle))) + rows* fabs(cos(radians(angle))))
        widthNew = int(rows * fabs(sin(radians(angle))) + cols* fabs(cos(radians(angle))))
        M[0, 2] += (widthNew - cols) / 2  
        M[1, 2] += (heightNew - rows) / 2 

        img = cv2.warpAffine(img, M, (widthNew, heightNew))
        a = M[:, :2]  ##a.shape (2,2)
        b = M[:, 2:]  ###b.shape(2,1)
        b = np.reshape(b, newshape=(1, 2))
        a = np.transpose(a)
        point = np.reshape(point, newshape=(len(point) * 4, 2))
        point = np.dot(point, a) + b
        point = np.reshape(point, newshape=(len(point) / 4, 8))
        return img, point

    函数keep_size参数用于是否进行裁剪和使用变化后的尺寸进行输出。下面是结果图:

                      原图                                                   裁剪图

                             未裁剪图

    对于我们进行目标检测来讲,裁剪图上的有些点的坐标已经超过了图像正常宽、高的取值范围。有可能四边形会切割成五边型,如何去处理此类的坐标点,我暂时没有想到好的方法,可以求交点来解决不知道对不对。但是,最好还是不要裁剪,然后resize后可以送入网络进行训练,这样可以节省好多不必要的麻烦。

    有什么问题,可以留言或者邮箱给我。

在使用LabelImg进行图像标注并保证图片旋转后标签框依然紧贴椭圆形边缘的过程中,你需要结合OpenCV、PIL等库来处理图像变换。这里是一个简单的Python代码示例: ```python import cv2 from PIL import Image, ImageDraw # 假设你已经保存了原始图片对应的LabelImg标注文件 image_path = 'image.jpg' mask_path = 'labels.png' # 加载图片和标签 img = Image.open(image_path) mask = Image.open(mask_path) # 获取标签中的椭圆形边界坐标,这通常由LabelImg提供一个包含每个矩形信息的JSON文件,例如: # {'boxes': [[x1, y1, x2, y2]], 'class_labels': ['elliptical_meter']...} with open('mask_annotations.json', 'r') as f: annotations = json.load(f) box = annotations['boxes'][0] # 椭圆的中心点和宽度、高度 center = (box[0], box[1]) width_height_ratio = (box[2] - box[0]) / (box[3] - box[1]) # 计算旋转后的椭圆坐标 def rotate_around_center(image, angle): center_point = tuple(np.array(image.size) / 2) rot_mat = cv2.getRotationMatrix2D(center_point, angle, 1.0) return cv2.warpAffine(image, rot_mat, image.shape[::-1], borderMode=cv2.BORDER_CONSTANT) angle = 45 # 你可以根据需求调整旋转角度 rotated_img = rotate_around_center(img, angle) rotated_mask = rotate_around_center(mask, angle) # 更新标签框,使其保持与旋转后的椭圆相对应 new_box = get_transformed_rectangle(box, angle, width_height_ratio) rotated_mask_draw = ImageDraw.Draw(rotated_mask) rotated_mask_draw.rectangle([new_box[0], new_box[1], new_box[2], new_box[3]], fill='white') # 可以将新的图片标注保存下来 rotated_img.save('rotated_image.jpg') rotated_mask.save('rotated_labels.png') def get_transformed_rectangle(rect, angle, ratio): # 简单的假设椭圆长轴与X轴平行,计算旋转后的新矩形 new_rect = [rect[0], rect[1], rect[0] + ratio * (rect[2] - rect[0]), rect[1]] matrix = cv2.getRotationMatrix2D((rect[0], rect[1]), angle, 1) rotated_rect = np.dot(matrix, np.array(new_rect).reshape(2, 2)).flatten().tolist() return rotated_rect
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值