这也太坑了,才知道opencv的图像坐标系居然是这样的——
(图引用自【opencv】图像坐标系的理解_RobotLaw的博客-CSDN博客_opencv坐标系)
虽然img.shape = h,w,C ,访问像素是[x,y], h代表x轴长度,即图像的高度,但是opencv会帮你做个转换,转成[y,x],然后用[y,x]去访问图片坐标系中的元素
平时单单用index访问还好,有opencv做转换,但是一旦涉及到鼠标选点,或者图片坐标系的变换(IPM)调用warpPerspective时,需要传入的图片参考点,就没人给你转了,这时候需要你自己处理。
本人就是因为这个问题,在做bev投影的时候被卡了好久,图片输出的 尺寸就是不对,无奈自己写了一个warpPerspective......
bug示例:
import os
import numpy as np
import cv2
import glob
dirlists = glob.glob('D:\\*',recursive=False)
dirname= dirlists[0]
basepic_path = os.path.join(dirname, 'camera_head_right.jpg')
bevpic_path = os.path.join(dirname, 'bev_visualize.jpg')
param_path = os.path.join(dirname, 'frame_infos.json')
label_path = os.path.join(dirname, 'semantic_label_cls3.png')
def ptlists(img):
H,W,_=img.shape
# return np.array([[0,0],[H-1,0],[0,W-1],[H-1,W-1]]).astype(np.float32)
return np.array([[0,0],[0,H-1],[W-1,0],[W-1,H-1]]).astype(np.float32)
basepic = cv2.imread(basepic_path,cv2.IMREAD_COLOR)
bevpic = cv2.imread(bevpic_path,cv2.IMREAD_COLOR)
def genbev(matrix=None):
if matrix is None:
matrix = cv2.getPerspectiveTransform(ptlists(basepic), ptlists(bevpic))
return cv2.warpPerspective(basepic,matrix, (bevpic.shape[1], bevpic.shape[0]),0), matrix
# return cv2.warpPerspective(basepic, np.linalg.inv(matrix), (bevpic.shape[1], bevpic.shape[0]),0), matrix
return cv2.warpPerspective(basepic, np.linalg.inv(matrix), (bevpic.shape[1], bevpic.shape[0]))
res, mat = genbev()
cv2.imshow('asd',res)
cv2.waitKey(0)
此程序是做bev投影的。如果把注释掉的部分回复,就是bug版本。主要区别在于定义参考点的时候的顺序。
另外,warpPerspective应该是默认开启了WARP_INVERSE这个flag的,所以传入的单应矩阵不用求逆。
下边是我自己写的warpPerspective,可以按正常坐标系顺序传参
def myownwarp(src,mat,size,scale=1):
h,w,_=size
h=int(h*scale)
w=int(w*scale)
out = np.zeros((h,w,3))
coory,coorx = np.meshgrid(np.arange(0,w),np.arange(0,h))
dst_coor = np.concatenate([
np.expand_dims(coorx,2),
np.expand_dims(coory,2),
np.ones((h,w,1))],axis=2)
src_coor = np.squeeze(mat @ np.expand_dims(dst_coor,3),3)
# print(np.expand_dims(dst_coor,3)[1000,700].shape)
# print(np.expand_dims(src_coor,3)[1000,700])
# print(mat @ np.expand_dims(dst_coor,3)[1000,700])
src_coor = src_coor / src_coor[:,:,2:]
dst_coor=dst_coor[:,:,0:2].astype(np.int32).reshape(-1,2)
src_coor=src_coor[:,:,0:2].astype(np.int32).reshape(-1,2)
out[dst_coor[:,0],dst_coor[:,1]]=src[src_coor[:,0],src_coor[:,1]]
return out.astype(np.int32)
matrix, _ = cv2.findHomography(ptlists(basepic), ptlists(bevpic), 0)
res = myownwarp(basepic,np.linalg.inv(matrix),bevpic.shape,1)
plt.imshow(res)