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

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

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  #a大于0
    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) #a>0逆时针,a<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呢!

 

posted @ 2018-05-03 15:00  outthinker  阅读(278)  评论(0编辑  收藏  举报