如何将透视网格上的距离转换为头部地图

huangapple go评论74阅读模式
英文:

How to convert distances on perspective grid to head map

问题

我正试图将人眼可观察到的物体位置从由固定摄像机拍摄的图像数据转移到俯视的2D场景中,显示区域没有纹理信息,只有物体的名称和位置。

然而,我不知道如何在谷歌中搜索我所需要的信息。

这是我使用的网格。

如何将透视网格上的距离转换为头部地图

这是透视网格图像。

如何将透视网格上的距离转换为头部地图

这是相机位置的内部信息。

如何将透视网格上的距离转换为头部地图

如果我说网格的每一边都是50厘米(因此一个正方形的区域是50x50),墙的高度是2.5米。

那么,有哪种方法可以用来生成一个热图,其中像素的颜色表示从墙到网格上的点的距离?

网格可以扩大到黑色空间。

以下是网格和透视网格的代码。

import cv2
import numpy as np
import imutils

# ...(此处省略了部分代码)
英文:

I am trying to transfer objects locations that can be observed by human eye on image data taken by fixed camera to 2d field displays the area from above without texture info but object names and location.

However, I don't know how to google that I need is below.

This is the grid I use.

如何将透视网格上的距离转换为头部地图

This is the perspectived grid image.

如何将透视网格上的距离转换为头部地图

And this is the insight how camera position is.

如何将透视网格上的距离转换为头部地图

If I say that every side on grid is 50 centimeters(so area is 50x50 for one square), and wall height is 2.5 meters.

So which method can be used to generate an heat map which pixel colors tell the distance from wall to the point on grid?

The grid can be enlarged to black spaces.

The below code for grid and perspectived grid.

import cv2
import numpy as np
import imutils


img = np.zeros((480,640),dtype=np.uint8)

size = 40
for i in range(int(img.shape[1]/size)+1):
    img = cv2.line(img, (i*size, 0), (i*size, img.shape[0]), thickness = 2, color = 255)

for i in range(int(img.shape[0]/size)+1):
    img = cv2.line(img, (0, i*size), (img.shape[1], i*size), thickness = 2, color = 255)

cv2.imshow("img",img)
cv2.waitKey(0)

h, w = img.shape
a = [
    [0, 0],
    [h - 1, 0],
    [0, w - 1],
    [h - 1, w - 1]]

pt_A = a[0]
pt_B = a[1]
pt_C = a[2]
pt_D = a[3]

width_AD = np.sqrt(((pt_A[0] - pt_D[0]) ** 2) + ((pt_A[1] - pt_D[1]) ** 2))
width_BC = np.sqrt(((pt_B[0] - pt_C[0]) ** 2) + ((pt_B[1] - pt_C[1]) ** 2))
maxWidth = max(int(width_AD), int(width_BC))
 
 
height_AB = np.sqrt(((pt_A[0] - pt_B[0]) ** 2) + ((pt_A[1] - pt_B[1]) ** 2))
height_CD = np.sqrt(((pt_C[0] - pt_D[0]) ** 2) + ((pt_C[1] - pt_D[1]) ** 2))
maxHeight = max(int(height_AB), int(height_CD))

input_pts = np.float32([pt_A, pt_B, pt_C, pt_D])
output_pts = np.float32([[800, 600], [900, 300], [-300, 500], [100, 200]])

def perspective(img, input_pts=input_pts, output_pts=output_pts, maxWidth=maxWidth, maxHeight=maxHeight):
    M = cv2.getPerspectiveTransform(input_pts,output_pts)

    out = cv2.warpPerspective(img,M,(maxWidth, maxHeight),flags=cv2.INTER_LINEAR)
    out = imutils.resize(out,height=500)
    return out


frame = perspective(img)
# Display image
cv2.imshow('frame', frame)
cv2.waitKey(0)

答案1

得分: 0

距离可以用毕达哥拉斯定理来计算:

如何将透视网格上的距离转换为头部地图

然后将结果映射到颜色并相应显示:

如何将透视网格上的距离转换为头部地图

import cv2
import numpy as np

img = np.zeros((480, 640), dtype=np.uint8)

size = 40
for i in range(int(img.shape[1] / size) + 1):
    img = cv2.line(img, (i * size, 0), (i * size, img.shape[0]), thickness=2,
                   color=255)

for i in range(int(img.shape[0] / size) + 1):
    img = cv2.line(img, (0, i * size), (img.shape[1], i * size), thickness=2,
                   color=255)

cv2.imshow("img", img)
cv2.waitKey(0)

h, w = img.shape
a = [
    [0, 0],
    [h - 1, 0],
    [0, w - 1],
    [h - 1, w - 1]]

pt_A = a[0]
pt_B = a[1]
pt_C = a[2]
pt_D = a[3]

width_AD = np.sqrt(((pt_A[0] - pt_D[0]) ** 2) + ((pt_A[1] - pt_D[1]) ** 2))
width_BC = np.sqrt(((pt_B[0] - pt_C[0]) ** 2) + ((pt_B[1] - pt_C[1]) ** 2))
maxWidth = max(int(width_AD), int(width_BC))

height_AB = np.sqrt(((pt_A[0] - pt_B[0]) ** 2) + ((pt_A[1] - pt_B[1]) ** 2))
height_CD = np.sqrt(((pt_C[0] - pt_D[0]) ** 2) + ((pt_C[1] - pt_D[1]) ** 2))
maxHeight = max(int(height_AB), int(height_CD))

input_pts = np.float32([pt_A, pt_B, pt_C, pt_D])
output_pts = np.float32([[800, 600], [900, 300], [-300, 500], [100, 200]])


def perspective(img, input_pts=input_pts, output_pts=output_pts,
                maxWidth=maxWidth, maxHeight=maxHeight):
    M = cv2.getPerspectiveTransform(input_pts, output_pts)

    out = cv2.warpPerspective(img, M, (maxWidth, maxHeight),
                              flags=cv2.INTER_LINEAR)
    return out

def calc_distance(cam_pos, img, tile_px, tile_size=50):
    """计算相机与地板之间的欧氏距离。"""
    cam_pos_x, cam_pos_y, cam_pos_z = cam_pos
    floor_size_x = int(img.shape[1] / tile_px) * tile_size
    floor_size_y = int(img.shape[0] / tile_px) * tile_size
    floor_pos_x, floor_pos_y = np.meshgrid(
        np.arange(img.shape[1]) / img.shape[1] * floor_size_x,
        np.arange(img.shape[0]) / img.shape[0] * floor_size_y)
    floor_pos_z = 0
    return np.sqrt(
        (floor_pos_x - cam_pos_x) ** 2 + (floor_pos_y - cam_pos_y) ** 2 + (
                    floor_pos_z - cam_pos_z) ** 2)

# 计算并归一化距离到[0, 255]
cam_pos = [0,0,250]
distance = calc_distance(cam_pos, img, size)
distance_img = ((distance - distance.min()) / (distance.max() - distance.min()) * 255).astype(np.uint8)

# 创建颜色编码的距离图像,去除非网格部分,显示透视图像
distance_img = cv2.applyColorMap(distance_img, cv2.COLORMAP_PARULA)
distance_img_grid = distance_img * img[..., None] / img.max()
frame = perspective(distance_img_grid)
# 显示图像
cv2.imshow('frame', frame)
cv2.waitKey(0)
英文:

The distance can be calculated in a pythagorean way:

如何将透视网格上的距离转换为头部地图

The result then can be mapped to a color and displayed accordingly:

如何将透视网格上的距离转换为头部地图

import cv2
import numpy as np

img = np.zeros((480, 640), dtype=np.uint8)

size = 40
for i in range(int(img.shape[1] / size) + 1):
    img = cv2.line(img, (i * size, 0), (i * size, img.shape[0]), thickness=2,
                   color=255)

for i in range(int(img.shape[0] / size) + 1):
    img = cv2.line(img, (0, i * size), (img.shape[1], i * size), thickness=2,
                   color=255)

cv2.imshow("img", img)
cv2.waitKey(0)

h, w = img.shape
a = [
    [0, 0],
    [h - 1, 0],
    [0, w - 1],
    [h - 1, w - 1]]

pt_A = a[0]
pt_B = a[1]
pt_C = a[2]
pt_D = a[3]

width_AD = np.sqrt(((pt_A[0] - pt_D[0]) ** 2) + ((pt_A[1] - pt_D[1]) ** 2))
width_BC = np.sqrt(((pt_B[0] - pt_C[0]) ** 2) + ((pt_B[1] - pt_C[1]) ** 2))
maxWidth = max(int(width_AD), int(width_BC))

height_AB = np.sqrt(((pt_A[0] - pt_B[0]) ** 2) + ((pt_A[1] - pt_B[1]) ** 2))
height_CD = np.sqrt(((pt_C[0] - pt_D[0]) ** 2) + ((pt_C[1] - pt_D[1]) ** 2))
maxHeight = max(int(height_AB), int(height_CD))

input_pts = np.float32([pt_A, pt_B, pt_C, pt_D])
output_pts = np.float32([[800, 600], [900, 300], [-300, 500], [100, 200]])


def perspective(img, input_pts=input_pts, output_pts=output_pts,
                maxWidth=maxWidth, maxHeight=maxHeight):
    M = cv2.getPerspectiveTransform(input_pts, output_pts)

    out = cv2.warpPerspective(img, M, (maxWidth, maxHeight),
                              flags=cv2.INTER_LINEAR)
    return out

def calc_distance(cam_pos, img, tile_px, tile_size=50):
    """Calculate eucledian distance between camera and floor."""
    cam_pos_x, cam_pos_y, cam_pos_z = cam_pos
    floor_size_x = int(img.shape[1] / tile_px) * tile_size
    floor_size_y = int(img.shape[0] / tile_px) * tile_size
    floor_pos_x, floor_pos_y = np.meshgrid(
        np.arange(img.shape[1]) / img.shape[1] * floor_size_x,
        np.arange(img.shape[0]) / img.shape[0] * floor_size_y)
    floor_pos_z = 0
    return np.sqrt(
        (floor_pos_x - cam_pos_x) ** 2 + (floor_pos_y - cam_pos_y) ** 2 + (
                    floor_pos_z - cam_pos_z) ** 2)

# calculate and normalize distance to [0, 255]
cam_pos = [0,0,250]
distance = calc_distance(cam_pos, img, size)
distance_img = ((distance - distance.min()) / (distance.max() - distance.min()) * 255).astype(np.uint8)

# create color coded distance image, remove non-grid parts, show perspective img
distance_img = cv2.applyColorMap(distance_img, cv2.COLORMAP_PARULA)
distance_img_grid = distance_img * img[..., None] / img.max()
frame = perspective(distance_img_grid)
# Display image
cv2.imshow('frame', frame)
cv2.waitKey(0)

huangapple
  • 本文由 发表于 2023年3月23日 09:04:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/75818464.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定