draw_tensor2psd.py——0126v2

import cv2

import numpy as np

import math

import os

import struct

from tqdm import tqdm

from glob import glob

PALETTE = np.random.randint(0, 255, 255, 3, dtype=np.uint32)

模型输入尺寸(W, H),用于把模型坐标缩放回原图

MODEL_IN_W = 608

MODEL_IN_H = 736

调试:同时输出"模型输入尺寸"和"交换W/H"的可视化

DEBUG_DRAW_MODEL_SIZE = True

DEBUG_DRAW_MODEL_SWAP = True

zh

imagespath = "/ai/DataSets/OD_FSD_zh/TI_test/rm/4/image/"

imagespath = "/ai/DataSets/OD_FSD_zh/TI_test/ppchen/DVR-20250804152834-2382380-PLR/image/"

savepath = "/ai/zhdata/multiyolov5_point_v2/test_images/out"

zh1 = 0

def readTensor(tensorFile):

global zh1

tensor = open(tensorFile,'rb')

infer_data = np.fromfile(tensor, dtype=np.int32)

print(infer_data.shape)

soltnum = int(len(infer_data) / 20)

im0 = cv2.imread(imagespath + tensorFile.split('/')-1:-8 + '.bmp')

if im0 is None:

print("读取图片失败:", tensorFile)

return

h0, w0 = im0.shape:2

sx = w0 / float(MODEL_IN_W)

sy = h0 / float(MODEL_IN_H)

point_all =\[\]

for i in range(soltnum):

point_dict1={}

raw_x1 = max(int(infer_data20\*i+6), 0)

raw_y1 = max(int(infer_data20\*i+7), 0)

raw_x2 = max(int(infer_data20\*i+8), 0)

raw_y2 = max(int(infer_data20\*i+9), 0)

raw_x3 = max(int(infer_data20\*i+10), 0)

raw_y3 = max(int(infer_data20\*i+11), 0)

raw_x4 = max(int(infer_data20\*i+12), 0)

raw_y4 = max(int(infer_data20\*i+13), 0)

x1 = max(int(raw_x1 * sx), 0)

y1 = max(int(raw_y1 * sy), 0)

x2 = max(int(raw_x2 * sx), 0)

y2 = max(int(raw_y2 * sy), 0)

x3 = max(int(raw_x3 * sx), 0)

y3 = max(int(raw_y3 * sy), 0)

x4 = max(int(raw_x4 * sx), 0)

y4 = max(int(raw_y4 * sy), 0)

zh = struct.unpack('!f',int(bin(infer_data20\*i+4)2:,2).to_bytes(4,byteorder='big'))

point_dict1"conf" = struct.unpack('!f',int(bin(infer_data20\*i+4)2:,2).to_bytes(4,byteorder='big'))0

point_dict1"isOccupied" = struct.unpack('!f',int(bin(infer_data20\*i+14)2:,2).to_bytes(4,byteorder='big'))0

point_dict1"isVIP" = struct.unpack('!f',int(bin(infer_data20\*i+15)2:,2).to_bytes(4,byteorder='big'))0

point_dict1"iswoman" = struct.unpack('!f',int(bin(infer_data20\*i+16)2:,2).to_bytes(4,byteorder='big'))0

point_dict1"isdisabled" = struct.unpack('!f',int(bin(infer_data20\*i+17)2:,2).to_bytes(4,byteorder='big'))0

point_dict1"ischarging" = struct.unpack('!f',int(bin(infer_data20\*i+18)2:,2).to_bytes(4,byteorder='big'))0

point_dict1"step" = struct.unpack('!f',int(bin(infer_data20\*i+19)2:,2).to_bytes(4,byteorder='big'))0

point_dict1"name" = str(struct.unpack('!f',int(bin(infer_data20\*i+5)2:,2).to_bytes(4,byteorder='big'))0)

point_dict1"delrule" = 0

point_dict1"pointx" = x1,x2,x3,x4

point_dict1"pointy" = y1,y2,y3,y4

if DEBUG_DRAW_MODEL_SIZE:

point_dict1"raw_pointx" = raw_x1, raw_x2, raw_x3, raw_x4

point_dict1"raw_pointy" = raw_y1, raw_y2, raw_y3, raw_y4

if x3 > 1000 or x4 > 1000 or x1 > 1000 or x2 > 1000 or y3 > 1000 or y4 > 1000 or y1 > 1000 or y2 > 1000:

zh1 +=1

kk = struct.unpack('!f',int(bin(infer_data20\*i+17)2:,2).to_bytes(4,byteorder='big'))0

print("数据解析错误"+ tensorFile + str(x3) + '--'+ str(zh1))

break

point_all.append(point_dict1)

end = len(point_all)

for i in range(len(point_all)):

if point_alli"delrule" == 0:

for j in range(i+1,end):

#简单就是求入口顶点之间的距离

xi1 = point_alli'pointx'0

yi1 = point_alli'pointy'0

xi2 = point_alli'pointx'1

yi2 = point_alli'pointy'1

xj1 = point_allj'pointx'0

yj1 = point_allj'pointy'0

xj2 = point_allj'pointx'1

yj2 = point_allj'pointy'1

if (abs(xi1 - xj1) + abs(yi1 - yj1)) < 40 or (abs(xi2 - xj2) + abs(yi2 - yj2)) < 40:

point_allj"delrule" = 1

for i in range(len(point_all)):

if point_alli"delrule" == 0:

line1 = point_all\[i'pointx'0,point_alli'pointy'0,point_alli'pointx'3,point_alli'pointy'3]

line2 = point_all\[i'pointx'1,point_alli'pointy'1,point_alli'pointx'2,point_alli'pointy'2]

vec1 =line1\[2-line10,line13-line11]

vec2 =line2\[2-line20,line23-line21]

#计算向量的点积和模长

dot_product = vec10 * vec20 + vec11 * vec21

m1 = math.sqrt(vec10**2 + vec11**2) + 0.000000000001

m2 = math.sqrt(vec20**2 + vec21**2) + 0.000000000001

val = dot_product/(m1 * m2)

if val > 1:

val = 1

if val < -1:

val = -15

radians = math.acos(val)

du = math.degrees(radians)

if du > 20:

point_alli"delrule" = 2

if 1:

for point_i in point_all:

if point_i"delrule" == 0:

if point_i"conf" > 0.45:#0.45

print(point_i"conf")

cv2.putText(im0, f'{point_i"conf":.3f}',

(point_i"pointx"0 + 6, point_i"pointy"0 + 6),

cv2.FONT_HERSHEY_PLAIN, 1.5, (0, 255, 0),2) #置信度

cv2.putText(im0, point_i"name",

(point_i"pointx"0 + 6, point_i"pointy"0 + 30),

cv2.FONT_HERSHEY_PLAIN, 1.5, (0, 255, 0),2) #类别

if float(point_i"isOccupied")> 0.1: #0.5

cv2.putText(im0, "Occ :" + f'{point_i"isOccupied":.3f}',

(point_i"pointx"0 + 6, point_i"pointy"0 + 54),

cv2.FONT_HERSHEY_PLAIN, 1.5, (0, 255, 0),2) #是否被占用

if float(point_i"isVIP") > 0.5:

cv2.putText(im0, "VIP :" + f'{point_i"isVIP":.3f}',

(point_i"pointx"0 + 6, point_i"pointy"0 + 78),

cv2.FONT_HERSHEY_PLAIN, 1.5, (0, 255, 0),2) #是否VIP车位

if float(point_i"iswoman") > 0.5:

cv2.putText(im0, "woman :" + f'{point_i"iswoman":.3f}',

(point_i"pointx"0 + 6, point_i"pointy"0 + 102),

cv2.FONT_HERSHEY_PLAIN, 1.5, (0, 255, 0),2) #是否女性车位

if float(point_i"isdisabled") > 0.5:

cv2.putText(im0, "disab :" + f'{point_i"isdisabled":.3f}',

(point_i"pointx"0 + 6, point_i"pointy"0 + 126),

cv2.FONT_HERSHEY_PLAIN, 1.5, (0, 255, 0),2) #是否残疾人车位

if float(point_i"ischarging") > 0.5:

cv2.putText(im0, "charg :" + f'{point_i"ischarging":.3f}',

(point_i"pointx"0 + 6, point_i"pointy"0 + 150),

cv2.FONT_HERSHEY_PLAIN, 1.5, (0, 255, 0),2) #是否充电车位

if float(point_i"step") > 0.5:

cv2.putText(im0, "step :" + f'{point_i"step":.3f}',

(point_i"pointx"0 + 6, point_i"pointy"0 + 174),

cv2.FONT_HERSHEY_PLAIN, 1.5, (0, 255, 0),2) #是否阶梯形车位

cv2.arrowedLine(im0, (point_i"pointx"0, point_i"pointy"0),(point_i"pointx"1, point_i"pointy"1), (0, 255, 0), 1, cv2.LINE_AA)

cv2.arrowedLine(im0, (point_i"pointx"1, point_i"pointy"1),(point_i"pointx"2, point_i"pointy"2), (255, 255, 0), 1, cv2.LINE_AA)

cv2.arrowedLine(im0, (point_i"pointx"2, point_i"pointy"2),(point_i"pointx"3, point_i"pointy"3), (255, 255, 0), 1, cv2.LINE_AA)

cv2.arrowedLine(im0, (point_i"pointx"3, point_i"pointy"3),(point_i"pointx"0, point_i"pointy"0), (255, 255, 0), 1, cv2.LINE_AA)

else:

cv2.putText(im0, f'{point_i"conf":.3f}',

(point_i"pointx"0 + 6, point_i"pointy"0 + 6),

cv2.FONT_HERSHEY_PLAIN, 2, (0, 0, 255),3)

cv2.arrowedLine(im0, (point_i"pointx"0, point_i"pointy"0),(point_i"pointx"1, point_i"pointy"1), (0, 0, 255), 1, cv2.LINE_AA)

cv2.arrowedLine(im0, (point_i"pointx"1, point_i"pointy"1),(point_i"pointx"2, point_i"pointy"2), (0, 0, 255), 1, cv2.LINE_AA)

cv2.arrowedLine(im0, (point_i"pointx"2, point_i"pointy"2),(point_i"pointx"3, point_i"pointy"3), (0, 0, 255), 1, cv2.LINE_AA)

cv2.arrowedLine(im0, (point_i"pointx"3, point_i"pointy"3),(point_i"pointx"0, point_i"pointy"0), (0, 0, 255), 1, cv2.LINE_AA)

if point_i"delrule" == 1:

cv2.putText(im0, f'{point_i"conf":.3f}',

(point_i"pointx"0 + 6, point_i"pointy"0 + 6),

cv2.FONT_HERSHEY_PLAIN, 2, (0, 0, 255),3)

cv2.arrowedLine(im0, (point_i"pointx"0, point_i"pointy"0),(point_i"pointx"1, point_i"pointy"1), (0, 0, 0), 1, cv2.LINE_AA)

cv2.arrowedLine(im0, (point_i"pointx"1, point_i"pointy"1),(point_i"pointx"2, point_i"pointy"2), (0, 0, 0), 1, cv2.LINE_AA)

cv2.arrowedLine(im0, (point_i"pointx"2, point_i"pointy"2),(point_i"pointx"3, point_i"pointy"3), (0, 0, 0), 1, cv2.LINE_AA)

cv2.arrowedLine(im0, (point_i"pointx"3, point_i"pointy"3),(point_i"pointx"0, point_i"pointy"0), (0, 0, 0), 1, cv2.LINE_AA)

if point_i"delrule" == 2:

cv2.putText(im0, f'{point_i"conf":.3f}',

(point_i"pointx"0 + 6, point_i"pointy"0 + 6),

cv2.FONT_HERSHEY_PLAIN, 2, (0, 0, 255),3)

cv2.arrowedLine(im0, (point_i"pointx"0, point_i"pointy"0),(point_i"pointx"1, point_i"pointy"1), (0, 0, 0), 1, cv2.LINE_AA)

cv2.arrowedLine(im0, (point_i"pointx"1, point_i"pointy"1),(point_i"pointx"2, point_i"pointy"2), (0, 0, 0), 1, cv2.LINE_AA)

cv2.arrowedLine(im0, (point_i"pointx"2, point_i"pointy"2),(point_i"pointx"3, point_i"pointy"3), (0, 0, 0), 1, cv2.LINE_AA)

cv2.arrowedLine(im0, (point_i"pointx"3, point_i"pointy"3),(point_i"pointx"0, point_i"pointy"0), (0, 0, 0), 1, cv2.LINE_AA)

zh = "/ai/TopViewMul/4/psd_out/" + tensorFile.split('/')-1:-8 + '.bmp'

print(zh)

cv2.imwrite(zh, im0)

if DEBUG_DRAW_MODEL_SIZE:

im_model = cv2.resize(im0, (MODEL_IN_W, MODEL_IN_H))

for point_i in point_all:

if point_i.get("raw_pointx") is None:

continue

if point_i"delrule" == 0 and point_i"conf" > 0.45:

cv2.arrowedLine(im_model, (point_i"raw_pointx"0, point_i"raw_pointy"0), (point_i"raw_pointx"1, point_i"raw_pointy"1), (0, 255, 0), 1, cv2.LINE_AA)

cv2.arrowedLine(im_model, (point_i"raw_pointx"1, point_i"raw_pointy"1), (point_i"raw_pointx"2, point_i"raw_pointy"2), (255, 255, 0), 1, cv2.LINE_AA)

cv2.arrowedLine(im_model, (point_i"raw_pointx"2, point_i"raw_pointy"2), (point_i"raw_pointx"3, point_i"raw_pointy"3), (255, 255, 0), 1, cv2.LINE_AA)

cv2.arrowedLine(im_model, (point_i"raw_pointx"3, point_i"raw_pointy"3), (point_i"raw_pointx"0, point_i"raw_pointy"0), (255, 255, 0), 1, cv2.LINE_AA)

zh_model = "/ai/TopViewMul/4/psd_out/" + tensorFile.split('/')-1:-8 + '_model.bmp'

cv2.imwrite(zh_model, im_model)

if DEBUG_DRAW_MODEL_SWAP:

im_model_swap = cv2.resize(im0, (MODEL_IN_H, MODEL_IN_W))

for point_i in point_all:

if point_i.get("raw_pointx") is None:

continue

if point_i"delrule" == 0 and point_i"conf" > 0.45:

cv2.arrowedLine(im_model_swap, (point_i"raw_pointx"0, point_i"raw_pointy"0), (point_i"raw_pointx"1, point_i"raw_pointy"1), (0, 255, 0), 1, cv2.LINE_AA)

cv2.arrowedLine(im_model_swap, (point_i"raw_pointx"1, point_i"raw_pointy"1), (point_i"raw_pointx"2, point_i"raw_pointy"2), (255, 255, 0), 1, cv2.LINE_AA)

cv2.arrowedLine(im_model_swap, (point_i"raw_pointx"2, point_i"raw_pointy"2), (point_i"raw_pointx"3, point_i"raw_pointy"3), (255, 255, 0), 1, cv2.LINE_AA)

cv2.arrowedLine(im_model_swap, (point_i"raw_pointx"3, point_i"raw_pointy"3), (point_i"raw_pointx"0, point_i"raw_pointy"0), (255, 255, 0), 1, cv2.LINE_AA)

zh_model_swap = "/ai/TopViewMul/4/psd_out/" + tensorFile.split('/')-1:-8 + '_model_swap.bmp'

cv2.imwrite(zh_model_swap, im_model_swap)

zh

for binpath in tqdm(glob(os.path.join("/ai/DataSets/OD_FSD_zh/TI_test/rm/2/psd/",'*.bin'))):

readTensor(binpath)

num=0

for binpath in tqdm(glob(os.path.join("/ai/TopViewMul/4/out_480_544_2039/psd/",'*.bin'))):

readTensor(binpath)

num+=1

if num==100:

print('exit')

exit(0)

------------------------------------------------

版权声明:本文为CSDN博主「weixin_39544891」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/weixin_39544891/article/details/157259451

我已经在 draw_tensor2psd.py 里加了调试输出,现在会额外生成一张"模型输入尺寸坐标系"的可视化图,文件名是 *_model.bmp(跟原输出同目录)。这张图直接用原始坐标(未缩放)画在 608×736 的图上,用来判断"坐标本身是否正确"。

你现在遇到"仍不对",请按这个顺序排查:


1) 先看 _model.bmp 是否正确(最关键)

  • 如果 _model.bmp 是正确的

→ 说明解码坐标没问题,问题一定在"映射回原图"

→ 下一步只需要检查:

  • 原图尺寸是否真的是 480×544
  • MODEL_IN_W/H 是否确认为 608×736
  • 是否存在"用错了原图文件"的情况(图不是推理时用的那张)
  • 如果 _model.bmp 也不正确

→ 说明问题在下位机解码/尺寸理解

→ 需要继续检查 inWidth/inHeight 是否与真实模型输入一致

→ 或者 inWidth/inHeight 在下位机实际是"反过来的"(W/H 颠倒)


2) 确认下位机实际输入尺寸

在 main.c 的 readInput() 里,已经打印了:

Image Pre processing for image of size %d x %d

你要确认输出里是:

  • 原图:480×544
  • 模型输入:608×736

如果这里打印的原图不是 480×544,说明你画的原图和推理用的原图不是同一张。


3) 快速验证 W/H 是否颠倒

你可以临时改一下:

MODEL_IN_W = 736

MODEL_IN_H = 608

如果这样 _model.bmp 反而更对,说明 W/H 在某处被当成 H/W 了(常见于配置或导出阶段)。


4) 验证 raw 坐标范围

在 draw_tensor2psd.py 里随便打印一个框的 raw 坐标:

if i == 0:

print("raw:", raw_x1, raw_y1, raw_x2, raw_y2, raw_x3, raw_y3, raw_x4, raw_y4)

正常情况下,raw 坐标应该落在:

  • x ∈ 0, 608
  • y ∈ 0, 736

如果超出很多,解码逻辑或尺度还不对。


5) 请你回传这两张图

  • 原输出(缩放到原图)
  • _model.bmp 输出

我可以直接对比两张图判断问题在哪一层。


如果你愿意,我也可以把脚本再升级成:

一次输出三张图(原图、模型输入图、W/H 交换图),这样一眼就能判断错在哪里。

已升级:现在会输出 三张图,用于快速定位 W/H 是否颠倒或映射有误。

输出文件:

  • 原图坐标(已缩放回原图):*_psd.bmp(原逻辑)
  • 模型输入坐标:*_model.bmp(608×736)
  • 交换 W/H 坐标:*_model_swap.bmp(736×608)

只要对比 _model.bmp 和 _model_swap.bmp 哪张更像"正确结果",就能判断 W/H 是否被某个环节搞反。

你明天跑完后,把三张图的效果描述或截图发我,我帮你继续定位。

下面是明天白天你在公司可以独立完成的排查清单,按优先级从"最有效"到"次要"排,尽量让你一次跑完把关键证据拿全:


1) 产出三张图(你现在的脚本已支持)

  • *_psd.bmp(原图坐标)
  • *_model.bmp(模型输入坐标 608×736)
  • *_model_swap.bmp(交换 W/H)

目标:判断坐标本身是否正确、是否 W/H 被反、是否只是映射问题。


2) 打印输入/输出的真实尺寸(主证据)

在下位机运行时,记录以下日志(main.c 里已有):

  • 原图尺寸:Image Pre processing for image of size W x H
  • 网络输入尺寸:inWidth/inHeight
  • 输出张量尺寸:outWidth/outHeight/outNumChannels

目标:确认"实际运行尺寸"和"你设定的尺寸"一致。


3) 验证 raw 坐标范围(最直观)

在 draw_tensor2psd.py 里临时加一行,只打印第一个检测框的 raw 坐标:

if i == 0:

print("raw:", raw_x1, raw_y1, raw_x2, raw_y2, raw_x3, raw_y3, raw_x4, raw_y4)

预期:

x 在 0~608、y 在 0~736 之间(如果不是,说明解码或尺寸理解仍不对)。


4) 排除"图像不是同一张"的问题

确认:

  • draw_tensor2psd.py 读取的图片名

  • 下位机推理使用的图片名

必须一致,否则映射一定错。


5) 快速排除 W/H 颠倒

你可以临时设置:

MODEL_IN_W = 736

MODEL_IN_H = 608

跑一张图看 _model_swap.bmp 是否明显更对。


6) 校验 bin 输出结构是否正常

你的 bin 每个目标 20 个 int(fwrite(&num0, 4, 20, fp)),所以:

  • len(infer_data) % 20 == 0
  • soltnum = len(infer_data)/20 正常

如果不是 20 的倍数,说明输出结构与解析不一致。


7) 如果还是不准,拿到"对照组"

同一张图在 PC 端(上位机)推理可视化一次,和下位机结果对比。

  • 若上位机对,下位机错 → 说明下位机解码流程不一致
  • 若上位机也错 → 说明训练/导出或 anchor/输出格式不一致

8) 若有时间:固定一张样本做最小复现

  • 只跑一张图
  • 保存原图、bin、三张可视化图

这样第二天我们直接定位不用再复现场景。


你明天做完后,只要把这四样信息发我,就能继续快速定位:

  1. 三张图中哪张最正确(psd / model / swap)

  2. 下位机日志:原图尺寸 & inWidth/inHeight

  3. raw 坐标范围(打印一条)

  4. 你确认的"图片名是否一致"

这样我们大概率能一次定位到问题根因。

相关推荐
机器学习之心1 天前
基于Stacking集成学习的回归预测模型:当PLS、SVM、BP、RF遇上BiLSTM
支持向量机·回归·集成学习·stacking
DXM05212 天前
第8期| 传统机器学习遥感解译:SVM & 随机森林分类全流程实操
人工智能·python·随机森林·机器学习·支持向量机·arcgis·自然语言处理
m沐沐2 天前
数据集的六种填充方法——下(使用众数填充+使用逻辑回归填充+使用随机森林填充)
python·随机森林·机器学习·pycharm·逻辑回归
m沐沐2 天前
【机器学习】7 种分类模型实战(逻辑回归→随机森林→SVM→AdaBoost→朴素贝叶斯→XGBoost→神经网络)
人工智能·pytorch·python·随机森林·机器学习·分类·逻辑回归
装不满的克莱因瓶4 天前
基于 sklearn 工具和鸢尾花数据集,进行逻辑回归实战
人工智能·python·机器学习·ai·逻辑回归·sklearn
scx_link4 天前
逻辑回归的总结
算法·机器学习·逻辑回归
数智工坊6 天前
周志华《Machine Learning》学习笔记--第六章--支持向量机
笔记·神经网络·学习·算法·机器学习·支持向量机
apcipot_rain6 天前
计科八股20260604——AI安全、K-means、SVM、nano
人工智能·神经网络·安全·支持向量机·kmeans
开开心心就好6 天前
免费智能证件合成工具,一键排版打印
windows·随机森林·计算机外设·word·逻辑回归·excel·csdn开发云
imDwAaY7 天前
机器学习入门:从感知机到逻辑回归,理解线性分类器与Softmax CS188 Note20 学习笔记
人工智能·笔记·python·学习·机器学习·逻辑回归