基于Deepsocial做社交安全距离监测时,先使用目标检测器检测出画面中的行人,然后建立从摄像机—透视图到逆透视—鸟瞰图的坐标映射,将摄像机拍摄画面中的行人坐标转换为鸟瞰图上的坐标,从而计算行人之间的距离。
先看一下原图:
想要把透视图转化为鸟瞰图,有两种做法:
1.在没有标定的情况下,只能选取四个点对
2.在有标定的情况下,可以直接使用标定的参数**
先不讲理论细节,先看第一个方法,直接看opencv的操作(使用图片Deepsocial使用的视频图片,以及Deepsocial中的标定坐标),首先需要以下条件:
1、在摄像机拍摄的图像上,比如在960*540的图像上选取四个角点,例如:
# 左上角、右上角、左下角、右下角
source = np.float32([[0, 0],[960, 0], [0, 540], [960,540]]
2、测量出四个点的实际坐标,例如:
target = np.float32([[180,162],[618,0],[552,540],[682,464]])
测量方式如下:
(待考究!!!)
先看一下转换后的鸟瞰图:
具体过程如下:
1、上述角点设置完毕后,通过pts1、pts2求出透视变换矩阵:
cv2.getPerspectiveTransform(source, target) 通过变换前后的四点坐标关系,获取透视变换的变换矩阵。
参数 source 为原图片中的四点坐标
参数 target 为目标图片中的四点坐标
数据格式如: [(x1,y1), (x2,y2),(x3,y3),(x4,y4)]
M = cv2.getPerspectiveTransform(source, target)
2、cv2.warpPerspective(image, M, dsize, flags, borderMode, borderValue) 依据变换矩阵 M 对图像 image 做透视变换:
参数 image 输入图像
参数 M变换矩阵
参数 dsize 变换后的目标图片大小, 元素顺序为 (width, height)
参数 flags 插值方式,cv2.INTER_LINEAR 或 cv2.INTER_NEAREST
参数 borderMode 边界补偿模式,cv2.BORDER_CONSTANT 或 cv2.BORDER_REPLICATE
参数 borderValue 边界补偿值,默认为0
warp_img = cv2.warpPerspective(image, M, (width, height), cv2.INTER_LINEAR ,cv2.BORDER_REPLICATE)
3、cv2.perspectiveTransform(point, M) 依据变换矩阵 M 对点 p 做透视变换,得到透视变换后的点坐标;
参数 point 原坐标点,如 (x,y)
参数 M 变换矩阵
#二维变三维, float型,
point = point.reshape(-1, 1, 2).astype(np.float32)
new_points = cv2.perspectiveTransform(points, trans_mat)
整体代码如下:
# -*- coding: utf-8 -*-
"""
Time : 2022/5/27 10:12
Author : cong
"""
import cv2
import numpy as np
#读入图片
img = cv2.imread('1.jpg')
H, W = img.shape[:2]
width = W
height = H
# 原图中的四个角点pts1(对应好即可,左上、右上、左下、右下),与变换后矩阵位置pts2
pts1 = np.float32([[0, 0], [width, 0], [0, height], [width, height]])
# pts2 = np.float32([[180, 162], [618, 0], [552, 540], [682, 464]])
pts2 = np.float32([[180, 162], [618, 0], [552, 540], [682, 464]])
# 生成透视变换矩阵;
## 说明获取逆透视变换矩阵函数各参数含义 ;src:源图像中待测矩形的四点坐标; sdt:目标图像中矩形的四点坐标
# cv2.getPerspectiveTransform(src, dst) → retval
M = cv2.getPerspectiveTransform(pts1, pts2)
print(M)
# cv2.warpPerspective(src, M, dsize[, dst[, flags[, borderMode[, borderValue]]]]) → dst
# src:输入图像; M:变换矩阵; dsize:目标图像shape; flags:插值方式,interpolation方法INTER_LINEAR或INTER_NEAREST;
# borderMode:边界补偿方式,BORDER_CONSTANT or BORDER_REPLICATE; borderValue:边界补偿大小,常值,默认为0
dst = cv2.warpPerspective(img, M, (width, height), cv2.INTER_LINEAR)
#显示图片
for i in range(4):
cv2.circle(img, (int(pts1[i][0]), int(pts1[i][1])), 10, (0, 0, 255), -1)
cv2.imwrite('ori_img.jpg', img)
cv2.imshow("img", img)
for i in range(4):
cv2.circle(dst, (int(pts2[i][0]), int(pts2[i][1])), 10, (0, 0, 255), -1)
cv2.imshow("dst", dst)
cv2.imwrite('wrap.jpg', dst)
cv2.waitKey(0)
#二维变三维, float型,
point = np.array([0,0])
point = point.reshape(-1, 1, 2).astype(np.float32)
new_points = cv2.perspectiveTransform(point, M)
参考链接:
https://blog.csdn.net/weixin_39863759/article/details/112115966
https://www.cnblogs.com/rabitvision/p/14044150.html