图像旋转及坐标变换

def sort_box(points): ###对输入的4个坐标排序【top-left, top-right, bottom-right, bottom-left】
        points = np.array(points)
        xSorted = points[np.argsort(points[:,0]),:]
        # grab the left-most and right-most points from the sorted
        # x-roodinate points
        leftMost = xSorted[:2, :]
        rightMost = xSorted[2:, :]
        if leftMost[0,1]!=leftMost[1,1]:
            leftMost=leftMost[np.argsort(leftMost[:,1]),:]
        else:
            leftMost=leftMost[np.argsort(leftMost[:,0])[::-1],:]
        (tl, bl) = leftMost
        if rightMost[0,1]!=rightMost[1,1]:
            rightMost=rightMost[np.argsort(rightMost[:,1]),:]
        else:
            rightMost=rightMost[np.argsort(rightMost[:,0])[::-1],:]
        (tr,br)=rightMost
        # return the coordinates in top-left, top-right,
        # bottom-right, and bottom-left order
        return np.array([tl, tr, br, bl], dtype="float32")

对box坐标进行左上角开始的顺时针排序

###根据透视变换将旋转的文本框纠正水平放置
def Perspective_img(boxes,image):
    image_h,image_w,_ = image.shape
    new_boxes = []
    for index,arbitrary_points in enumerate(boxes):
        h = pointDistance(arbitrary_points[0],arbitrary_points[1])
        w = pointDistance(arbitrary_points[3],arbitrary_points[0])
        rectangle = np.float32([[0, h], [0, 0], [w, 0], [w, h]])
        M = cv2.getPerspectiveTransform(arbitrary_points, rectangle)
        doc_dst = cv2.warpPerspective(image, M, (w, h))
        cv2.imwrite(f'./test_rotate/rotate_img_{index}.jpg',doc_dst)
        new_boxes.append(doc_dst)
    return new_boxes

根据透视变换将旋转的文本框纠正水平放置 

###根据文本框的方向得到整张图像的方向
def get_angle(boxes):
    all_angles = []
    for index,box in enumerate(boxes):
        box = sort_box(box)
        mid2 = (box[0] + box[3]) / 2
        mid1 = (box[1] + box[2]) / 2
        x = math.atan2(mid1[1]-mid2[1],mid1[0]-mid2[0])  ###先传递y坐标,后x坐标
        angle = x * 180 / math.pi  ###范围[-180,180]
        all_angles.append(angle)
    min_angle = int(min(all_angles))
    max_angle = int(max(all_angles))
    ###划分的区间
    interal = [x for x in range(min_angle,max_angle,3)]
    if len(interal) > 1:
        s = pd.cut(all_angles,bins=interal)
        final_angle = int(pd.value_counts(s).idxmax().mid)
    else:
        final_angle = int((min_angle + max_angle) / 2)
    return final_angle

根据多个文本框的中心线统计整张图像的角度

# 根据旋转angle角度,旋转图像,缺失背景白色(255, 255, 255)填充
def rotate_bound_white_bg(image,boxes, 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)
    # -angle位置参数为角度参数负值表示顺时针旋转; 1.0位置参数scale是调整尺寸比例(图像缩放参数),建议0.75
    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
    # borderValue 缺失背景填充色彩,此处为白色,可自定义
    rotated_image = cv2.warpAffine(image, M, (nW, nH),borderValue=(255,255,255))
    ###根据仿射变化矩阵求新的坐标
    rotated_boxes = copy.deepcopy(boxes)
    for index_box,box_points in enumerate(rotated_boxes):
        for index_point, point in enumerate(box_points):
            new_point = np.sum(point* M[:2,:2],axis=1) + M[:,2]
            rotated_boxes[index_box,index_point,:] = new_point
    return rotated_image,rotated_boxes

根据图片的角度旋转图像,并对box的坐标也做相对应的旋转

以下是对旋转图像公式的推导

 坐标通过旋转矩阵得到新的坐标公式

根据上面的公式旋转矩阵M得到

new_point = np.sum(point* M[:2,:2],axis=1) + M[:,2]

X_new  =  X_old  *  cos(a)   +  Y_old  *  sin(a)  + dx

Y_new  =  X_old  *  -sin(a)   +  Y_old  *  cos(a)  + dy

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值