ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

旋转图片及标注lable的实现

2020-12-26 19:01:20  阅读:214  来源: 互联网

标签:lable rotate bb cv2 旋转 np new rotation 标注


旋转图片相关内容

背景

1、做带角度的图像数据增强,一般使用rotate函数就可以,不过有时图片部分角就会旋转出去,如果不丢失信息,且补边呢?
2、如果标注的label是一个矩形,如果旋转后,想让label也跟着旋转,怎么计算

旋转理论

旋转图片一般用到了仿射变换,仿射变换的原理可以从几何理解,也可以从极坐标方式理解,具体计算方式就是矩阵相乘
在这里插入图片描述

OpenCV旋转操作及原理

OpenCV的方法是cv2.getRotationMatrix2D()方法,调用如下:

# 你是在
matRotate2 = cv2.getRotationMatrix2D((0, 0),30, 1.0)
print(matRotate2)

#output
[[ 0.8660254  0.5       -0.1830127]
 [-0.5        0.8660254  0.3169873]]

其中这个函数的源码如下:

cv::Mat cv::getRotationMatrix2D( Point2f center, double angle, double scale )
{
    angle *= CV_PI/180;
    double alpha = cos(angle)*scale;
    double beta = sin(angle)*scale;

    Mat M(2, 3, CV_64F);
    double* m = (double*)M.data;

    m[0] = alpha;
    m[1] = beta;
    m[2] = (1-alpha)*center.x - beta*center.y;
    m[3] = -beta;
    m[4] = alpha;
    m[5] = beta*center.x + (1-alpha)*center.y;
    return M;
}
}

代码参考的公式为1
在这里插入图片描述
那这个公式是怎么推导的呢,原理是将旋转轴心转移到坐标中心点,旋转后,再放回原来位置2
在这里插入图片描述

旋转图像及标注框

基本操作就是所有的像素点与之变换矩阵相乘,标签与之相乘,具体代码详解参考了图像增强3,新的宽高计算入下图4
在这里插入图片描述
图像旋转代码如下4

def rotate_box(bb, cx, cy, h, w):
    new_bb = list(bb)
    for i,coord in enumerate(bb):
        # opencv calculates standard transformation matrix
        M = cv2.getRotationMatrix2D((cx, cy), theta, 1.0)
        # Grab  the rotation components of the matrix)
        cos = np.abs(M[0, 0])
        sin = np.abs(M[0, 1])
        # compute the new bounding dimensions of the image
        nW = int((h * sin) + (w * cos))
        nH = int((h * cos) + (w * sin))
        # adjust the rotation matrix to take into account translation
        M[0, 2] += (nW / 2) - cx
        M[1, 2] += (nH / 2) - cy
        # Prepare the vector to be transformed
        v = [coord[0],coord[1],1]
        # Perform the actual rotation and return the image
        calculated = np.dot(M,v)
        new_bb[i] = (calculated[0],calculated[1])
    return new_bb

点的转换模型如下:

def rotate_box(bb, cx, cy, h, w):
    new_bb = list(bb)
    for i,coord in enumerate(bb):
        # opencv calculates standard transformation matrix
        M = cv2.getRotationMatrix2D((cx, cy), theta, 1.0)
        # Grab  the rotation components of the matrix)
        cos = np.abs(M[0, 0])
        sin = np.abs(M[0, 1])
        # compute the new bounding dimensions of the image
        nW = int((h * sin) + (w * cos))
        nH = int((h * cos) + (w * sin))
        # adjust the rotation matrix to take into account translation
        M[0, 2] += (nW / 2) - cx
        M[1, 2] += (nH / 2) - cy
        # Prepare the vector to be transformed
        v = [coord[0],coord[1],1]
        # Perform the actual rotation and return the image
        calculated = np.dot(M,v)
        new_bb[i] = (calculated[0],calculated[1])
    return new_bb

效果图如下
在这里插入图片描述

附代码,基本参考是Image rotation using OpenCV

# -*- coding: utf-8 -*-
"""
-------------------------------------------------
   File Name:     a6_rotate_with_box.py
   Description :
   Author :       lj_tal
   date:          2020/12/26
-------------------------------------------------
"""
import cv2
import numpy as np

def cocoBbox2Point4(coco_bbox):
    xmin = coco_bbox[0]
    ymin = coco_bbox[1]
    xmax = coco_bbox[2]
    ymax = coco_bbox[3]
    points = np.array([[xmin, ymax], [xmin, ymin], [xmax, ymin], [xmax, ymax]], dtype=np.int).reshape(4, 2)
    return points

def point42CocoBbox(bbox_numpy):
    bbox_temp = bbox_numpy.reshape(4,2)
    xmin = np.min(bbox_temp[:,0])
    xmax = np.max(bbox_temp[:,0])
    ymin = np.min(bbox_temp[:,1])
    ymax = np.max(bbox_temp[:,1])
    # print([xmin,ymin,xmax,ymax])
    return np.array([xmin,ymin,xmax,ymax]).astype(np.int)

# point2 = point42CocoBbox(points)
point4 = np.asarray([35 , 50, 175, 215])
print(point4)

def rotate_bound(image, angle):
    # grab the dimensions of the image and then determine the
    # center
    (h, w) = image.shape[:2]
    (cX, cY) = (w // 2, h // 2)
    # grab the rotation matrix (applying the negative of the
    # angle to rotate clockwise), then grab the sine and cosine
    # (i.e., the rotation components of the matrix)
    M = cv2.getRotationMatrix2D((cX, cY), angle, 1.0)
    cos = np.abs(M[0, 0])
    sin = np.abs(M[0, 1])
    # compute the new bounding dimensions of the image
    nW = int((h * sin) + (w * cos))
    nH = int((h * cos) + (w * sin))
    # adjust the rotation matrix to take into account translation
    M[0, 2] += (nW / 2) - cX
    M[1, 2] += (nH / 2) - cY
    # perform the actual rotation and return the image
    return cv2.warpAffine(image, M, (nW, nH))


def rotate_box(bb, cx, cy, h, w,angle):
    new_bb = list(bb)
    for i,coord in enumerate(bb):
        # opencv calculates standard transformation matrix
        M = cv2.getRotationMatrix2D((cx, cy), angle, 1.0)
        # Grab  the rotation components of the matrix)
        cos = np.abs(M[0, 0])
        sin = np.abs(M[0, 1])
        # compute the new bounding dimensions of the image
        nW = int((h * sin) + (w * cos))
        nH = int((h * cos) + (w * sin))
        # adjust the rotation matrix to take into account translation
        M[0, 2] += (nW / 2) - cx
        M[1, 2] += (nH / 2) - cy
        # Prepare the vector to be transformed
        v = [coord[0],coord[1],1]
        # Perform the actual rotation and return the image
        calculated = np.dot(M,v)
        new_bb[i] = [calculated[0],calculated[1]]
    return new_bb

if __name__ == '__main__':

    img = cv2.imread('cat.jpg')
    print(img.shape)

    theta = 20

    point8_list = np.asarray([[[776.9486798180992, 383.9884930278827], [881.0203274611703, 380.39981552294927], [884.6090049661037, 498.8261731857542], [780.5373573230327, 498.8261731857542]],
    [[897.1693762333709, 534.712948235089], [999.4466851239752, 538.3016257400226], [1003.0353626289086, 653.139305897894], [900.7580537383044, 653.139305897894]],
    [[1279.3635305087869, 111.24900265293799], [1293.718240528521, 805.6580998575671], [624.4298858584261, 787.7147123328997], [628.0185633633596, 113.04334140540473]]])

    rotated_img = rotate_bound(img,theta)
    a_img = img.copy()
    for point8 in point8_list:
        point4 = point42CocoBbox(point8)
        cv2.rectangle(a_img, (point4[0], point4[1]), (point4[2], point4[3]), (255, 0, 0), 1)
    #
    cv2.imshow('aa',a_img)
    cv2.imwrite('cat_a.jpg',a_img)
    cv2.waitKey(0)


    # Calculate the shape of rotated images
    (heigth, width) = img.shape[:2]
    (cx, cy) = (width // 2, heigth // 2)
    (new_height, new_width) = rotated_img.shape[:2]
    (new_cx, new_cy) = (new_width // 2, new_height // 2)
    print(cx,cy,new_cx,new_cy)
    new_bb = {}

    for points8 in point8_list:

        points8_rotate= rotate_box(points8, cx, cy, heigth, width,theta)
        points8_rotate = np.asarray(points8_rotate).astype(np.int)

        print(points8_rotate)
        points8_rotate = points8_rotate.reshape((-1, 1, 2))
        new_image = cv2.polylines(rotated_img, [points8_rotate], True, (255, 0, 0), 1)
    cv2.imwrite('cat_b.jpg',new_image)

    cv2.imshow('bb',new_image)

    cv2.waitKey(0)

参考


  1. https://blog.csdn.net/u011681952/article/details/98942207 ↩︎

  2. https://math.stackexchange.com/questions/2093314/rotation-matrix-of-rotation-around-a-point-other-than-the-origin ↩︎

  3. https://blog.paperspace.com/data-augmentation-for-object-detection-rotation-and-shearing/ ↩︎

  4. https://cristianpb.github.io/blog/image-rotation-opencv ↩︎ ↩︎

标签:lable,rotate,bb,cv2,旋转,np,new,rotation,标注
来源: https://blog.csdn.net/loovelj/article/details/111758857

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有