• 对图像进行相关计算操作时注意的问题!


    这里我以图像旋转为例,功能是图像旋转后依然被完全包含(且没有“蜂窝煤”效应)

    def rotation(src_img_size , crop_img , src_box_info , angle):  #返回旋转后的pts坐标和boc框
        src_height = int(src_img_size[0])  #原始图片尺寸
        src_width = int(src_img_size[1])
        crop_height = crop_img.shape[0]  #截取的图片尺寸
        crop_width = crop_img.shape[1]
        #tar_rotation_pts = np.zeros((4 , 2) , dtype = int)
        tar_box_info = np.zeros((2 , 2) , dtype = int)  #存储缩放后的box框
        a = angle
        angle_pi = a * math.pi / 180.0
        #================================================================================================
        #图片进行旋转
        src_peak = np.zeros((4 , 2) , dtype = int)  #二维框的四个顶点
        src_peak[0][0] = int(src_box_info[0])  #左上角点
        src_peak[0][1] = int(src_box_info[1])
        src_peak[1][0] = int(src_box_info[0]) + crop_width  #右上角点
        src_peak[1][1] = int(src_box_info[1])
        src_peak[2][0] = int(src_box_info[0])  #左下角点
        src_peak[2][1] = int(src_box_info[1]) + crop_height
        src_peak[3][0] = int(src_box_info[0]) + crop_width #右下角点
        src_peak[3][1] = int(src_box_info[1]) + crop_height
        print(src_peak)
        tar_peak = np.zeros((4 , 2) , dtype = int)
        for i in range(len(src_peak)):
            tar_peak[i][0] = int(int(src_peak[i][0]) * math.cos(angle_pi) - int(src_peak[i][1]) * math.sin(angle_pi) - 0.5 * src_width * math.cos(angle_pi) + 0.5 * src_height * math.sin(angle_pi) + 0.5 * src_width)
            tar_peak[i][1] = int(int(src_peak[i][0]) * math.sin(angle_pi) + int(src_peak[i][1]) * math.cos(angle_pi) - 0.5 * src_width * math.sin(angle_pi) - 0.5 * src_height * math.cos(angle_pi) + 0.5 * src_height)
        
        print(tar_peak)
        max_x = tar_peak[0][0]
        for j in range(4):
            if(tar_peak[j][0] > max_x):
                max_x = tar_peak[j][0]
        min_x = tar_peak[0][0]
        for j in range(4):
            if(tar_peak[j][0] < min_x):
                min_x = tar_peak[j][0]
        max_y = tar_peak[0][1]
        for j in range(4):
            if(tar_peak[j][1] > max_y):
                max_y = tar_peak[j][1]
        min_y = tar_peak[0][1]
        for j in range(4):
            if(tar_peak[j][1] < min_y):
                min_y = tar_peak[j][1]
    
        origin_min_x = min_x
        origin_max_x = max_x
        origin_min_y = min_y
        origin_max_y = max_y 
        print(min_x , max_x)
        print(min_y , max_y)
    
        if(min_x > src_box_info[0]):
            min_x = src_box_info[0]
        if(max_x < src_box_info[2]):
            max_x = src_box_info[2]
        if(min_y > src_box_info[1]):
            min_y = src_box_info[1]
        if(max_y < src_box_info[3]):
            max_y = src_box_info[3]
    
        tar_width = max_x - min_x
        tar_height = max_y - min_y
        #对crop_img先进行操作,使得旋转后图片依然完全包含整个二维框
        rotation_size = (tar_height + 1 , tar_width + 1 , 3)  #rotation_size:(271 , 271);crop_size:(174 , 270)
        rotation_img = np.zeros(rotation_size , np.uint8)
    
        print(rotation_size)
        print(crop_height , crop_width)
    
        for i in range(crop_height):
            for j in range(crop_width):
                x = j + (src_box_info[0] - min_x)  #注意!这里的i和j是二维框的坐标系,而y和x是rotation_img的坐标系,所以需要先进行坐标系转换
                y = i + (src_box_info[1] - min_y)
                rotation_img[y , x] = crop_img[i , j]
    
        cv2.imwrite("D:/projects/three_views/gen_train_lmdb/small_test/2.jpg" , rotation_img)
    
        #crop_img进行旋转
        center = ((src_width / 2 - min_x) , (src_height / 2 - min_y))  #旋转中心设为图片中心,同时由于这儿是对crop_img(扩展后的)进行旋转,所以旋转中心的参考坐标系应该变成扩展后的crop_img的坐标系,所以这里也要进行一步操作
        M = cv2.getRotationMatrix2D(center, (a * (-1)), 1.0)  #顺时针旋转
        tar_rotation_img = cv2.warpAffine(rotation_img, M, (tar_width, tar_height))  #旋转后的图片
        #===============================================================================
        if(origin_min_x <= src_box_info[0]):
            origin_min_x = 0
        else:
            origin_min_x = origin_min_x - src_box_info[0]
        if(origin_max_x >= src_box_info[2]):
            origin_max_x = tar_width
        else:
            origin_max_x = origin_max_x - min_x
        #=======
        if(origin_min_y >= src_box_info[1]):
            origin_min_y = origin_min_y - src_box_info[1]
        else:
            origin_min_y = 0
        if(origin_max_y <= src_box_info[3]):
            origin_max_y = origin_max_y - min_y
        else:
            origin_max_y = tar_height
        #=================================================================================
        tar_rotation_img = tar_rotation_img[int(origin_min_y) : int(origin_max_y) , int(origin_min_x) : int(origin_max_x) , :]
        #======================================================================================================
        #box信息:(cx , cy , w , h)
        tar_box_info[0][0] = src_width / 2
        tar_box_info[0][1] = src_height / 2
        tar_box_info[1][0] = origin_max_x - origin_min_x
        tar_box_info[1][1] = tar_height
        #======================================================================================================
        #旋转后的pts信息
        '''for i in range(len(src_pts) / 2):
            tar_rotation_pts[i][0] = int(int(src_pts[2 * i]) * math.cos(angle_pi) - int(src_pts[2 * i + 1]) * math.sin(angle_pi) - 0.5 * src_width * math.cos(angle_pi) + 0.5 * src_height * math.sin(angle_pi) + 0.5 * src_width)
            tar_rotation_pts[i][1] = int(int(src_pts[2 * i]) * math.sin(angle_pi) + int(src_pts[2 * i + 1]) * math.cos(angle_pi) - 0.5 * src_width * math.sin(angle_pi) - 0.5 * src_height * math.cos(angle_pi) + 0.5 * src_height)'''
        return tar_rotation_img , tar_box_info 

    在操作的时候,要非常注意的一个问题就是:要能敏锐地察觉到图像中坐标系的变换!!!举下面这个例子:

    for i in range(crop_height):
            for j in range(crop_width):
                x = j + (src_box_info[0] - min_x)  #注意!这里的i和j是二维框的坐标系,而y和x是rotation_img的坐标系,所以需要先进行坐标系转换
                y = i + (src_box_info[1] - min_y)
                rotation_img[y , x] = crop_img[i , j]

    其中i和j是在crop_img坐标系下,而y和x是在rotation_img坐标系下,所以在操作的时候一定要注意先变换到同一坐标系下;

    上面这个例子还比较明显,但还有很多时候是不明显的,所以就需要我们敏锐地观察力,否则的确是个很难查的BUG呢!

  • 相关阅读:
    洛谷P1724 东风谷早苗
    hdu 1001 Sum Problem
    洛谷 P1006 传纸条
    codevs 6116 区间素数
    LibreOJ #101. 最大流
    洛谷 P1455 搭配购买
    LibreOJ #119. 最短路 (堆优化dijkstra)
    LibreOJ #109. 并查集
    COGS.1200 ganggang的烦恼
    uoj #15. 【NOIP2014】生活大爆炸版石头剪刀布
  • 原文地址:https://www.cnblogs.com/zf-blog/p/8985360.html
Copyright © 2020-2023  润新知