基于单目相机的2D测量(工件尺寸和物体尺寸)

目录

1.简介

2.基于单目相机的2D测量

2.1 想法:

2.2 代码思路

2.2 主函数部分


1.简介

基于单目相机的2D测量技术在许多领域中具有重要的背景和意义。

  1. 工业制造:在工业制造过程中,精确测量是确保产品质量和一致性的关键。基于单目相机的2D测量技术可以用于检测和测量零件尺寸、位置、形状等参数,进而实现自动化生产和质量控制。通过实时监测并反馈测量结果,可以快速发现和纠正生产中的偏差,提高产品的一致性和合格率。

  2. 计算机视觉:单目相机作为计算机视觉的传感器之一,能够捕捉并记录场景中的图像信息。基于单目相机的2D测量技术可以通过对图像进行处理和分析来提取目标物体的特征和参数。这种技术在目标检测、物体跟踪、姿态估计等计算机视觉任务中起着至关重要的作用。

  3. 地理测绘和导航:基于单目相机的2D测量技术可以应用于地理测绘和导航领域。通过获取地面或航空图像,并利用图像处理和计算机视觉算法,可以实现地表特征的提取、地形建模、数字地图的生成等工作。这对于城市规划、农业管理、导航系统等方面具有重要的应用价值。

  4. 医学影像:在医学领域,基于单目相机的2D测量技术可以用于医学影像的分析和测量。通过对医学图像进行处理和分析,可以提取器官、病灶的形状、大小、位置等信息,辅助医生进行诊断和治疗决策。这种技术在影像学、放射学、眼科等医学专业中得到广泛应用。

综上所述,基于单目相机的2D测量技术在工业制造、计算机视觉、地理测绘和导航、医学影像等领域都有着重要的背景和意义。它可以提高生产效率、产品质量,推动科学研究和医学进步,为各个领域带来更多的机遇和挑战。

2.基于单目相机的2D测量

2.1 想法:

因为是静态测量,所以核心测量算法使用仿射变换。

首先拿到参照物区域,进行真实距离和像素距离的尺寸换算

在参照物区域找到物体轮廓,进行多边形拟合,对拟合到的物体进行测量

2.2 代码思路

代码思路的简要描述:

  1. 导入所需的库,包括cv2和自定义的utlis

  2. 初始化一些变量,如是否使用网络摄像机 (webcam)、图像路径 (path)、捕获对象 (cap)、图像缩放比例 (scale)、纸张宽度和高度 (wPhP) 以及上一帧时间 (pTime)。

  3. 进入主循环。在每次循环中,如果使用网络摄像机,则读取图像帧;否则,从指定路径读取图像。

  4. 对图像进行轮廓检测,获取所有检测到的轮廓 (conts) 和最大轮廓 (biggest)。

  5. 使用最大轮廓对图像进行透视变换 (warpImg),得到纸张的鸟瞰图 (imgWarp)。

  6. 对纸张鸟瞰图进行轮廓检测,获取所有检测到的轮廓 (conts2)。

  7. 遍历每个轮廓对象,绘制轮廓线和箭头,并计算测量结果 (纸张宽度 nW 和高度 nH)。

  8. 在图像上绘制测量结果和帧率信息。

  9. 显示原始图像和处理后的图像。

  10. 等待按键,继续下一次循环。

以上是代码的简要思路,具体实现和功能可以参考代码中的注释。

关于复现,你可以准备一张A4纸,一张小卡片,或者边缘信息明显的其他物件,按照图片中方式摆放即可。

像素与真实距离换算为

3像素=1mm

检测帧率可达30帧,误差在2%(误差取决相机分辨率),缺点是无法检测轮廓不清晰的物件以及复杂物体。

下一篇介绍如何测量复杂形状的物体

2.2 主函数部分

import cv2
import utlis
import time###################################
webcam = True  # 网络摄像机一开始为FALSE
path = '1.jpg'
cap = cv2.VideoCapture(0)  # 使用捕获和cv定义相机-点点视频捕获,,我们将定义id,因此在这种情况下为0
cap.set(10, 160)  # 设置参数,宽度,高度,亮度,为他们中的每一根写入间隙点集,具有不同的亮度id,有十个,所以将其保持为160,然后在宽度和高度上,宽度为3,1920
cap.set(3, 1920)
cap.set(4, 1080)
scale = 3
wP = 270 * scale
hP = 370 * scale
###################################
pTime = 0
while True:if webcam:success, img = cap.read()else:img = cv2.imread(path)imgContours, conts = utlis.getContours(img, minArea=50000, filter=4)if len(conts) != 0:biggest = conts[0][2]# print(biggest)imgWarp = utlis.warpImg(img, biggest, wP, hP)imgContours2, conts2 = utlis.getContours(imgWarp,minArea=2000, filter=4,cThr=[50, 50], draw=False)if len(conts) != 0:for obj in conts2:cv2.polylines(imgContours2, [obj[2]], True, (0, 255, 0), 2)nPoints = utlis.reorder(obj[2])nW = round((utlis.findDis(nPoints[0][0] // scale, nPoints[1][0] // scale) / 10), 1)nH = round((utlis.findDis(nPoints[0][0] // scale, nPoints[2][0] // scale) / 10), 1)cv2.arrowedLine(imgContours2, (nPoints[0][0][0], nPoints[0][0][1]),(nPoints[1][0][0], nPoints[1][0][1]),(255, 0, 255), 3, 8, 0, 0.05)cv2.arrowedLine(imgContours2, (nPoints[0][0][0], nPoints[0][0][1]),(nPoints[2][0][0], nPoints[2][0][1]),(255, 0, 255), 3, 8, 0, 0.05)x, y, w, h = obj[3]cv2.putText(imgContours2, '{}cm'.format(nW), (x + 30, y - 10), cv2.FONT_HERSHEY_COMPLEX_SMALL, 1.5,(255, 0, 255), 2)cv2.putText(imgContours2, '{}cm'.format(nH), (x - 70, y + h // 2), cv2.FONT_HERSHEY_COMPLEX_SMALL, 1.5,(255, 0, 255), 2)cTime = time.time()fps = 1 / (cTime - pTime)pTime = cTimecv2.putText(imgContours2, str(int(fps)), (10, 70), cv2.FONT_HERSHEY_PLAIN, 3,(255, 0, 255), 3)# 图像预处理及边缘检测cv2.imshow('A4', imgContours2)img = cv2.resize(img, (0, 0), None, 0.5, 0.5)cv2.imshow('Original', img)cv2.waitKey(1)

utlis模块代码

import cv2
import numpy as np
import math
import time
def getContours(img, cThr=[100, 100], showCanny=False, minArea=5000, filter=0, draw=False):# 将输入图像转换为灰度图像imgGray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# 对灰度图像进行高斯模糊imgBlur = cv2.GaussianBlur(imgGray, (5, 5), 1)# 使用Canny边缘检测算法得到边缘图像imgCanny = cv2.Canny(imgBlur, cThr[0], cThr[1])# 对Canny边缘图像进行膨胀操作kernel = np.ones((5, 5))imgDial = cv2.dilate(imgCanny, kernel, iterations=3)# 对膨胀后的图像进行腐蚀操作imgThre = cv2.erode(imgDial, kernel, iterations=1)# gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# blurred = cv2.GaussianBlur(gray, (5, 5), 0)# kernal = np.ones((5, 5), np.uint8)# blurred = cv2.erode(blurred, kernal)  # 腐蚀# blurred = cv2.erode(blurred, kernal)# edges = cv2.Canny(blurred, 50, 150)# 寻找图像中的轮廓contours, hierarchy = cv2.findContours(imgThre, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)finalContours = []for i in contours:area = cv2.contourArea(i)# 仅保留面积大于minArea的轮廓if area > minArea:peri = cv2.arcLength(i, True)approx = cv2.approxPolyDP(i, 0.02 * peri, True)bbox = cv2.boundingRect(approx)if filter > 0:# 如果指定了过滤条件,仅保留满足条件的轮廓if len(approx) == filter:finalContours.append([len(approx), area, approx, bbox, i])else:finalContours.append([len(approx), area, approx, bbox, i])# 根据面积对轮廓进行排序finalContours = sorted(finalContours, key=lambda x: x[1], reverse=True)if draw:# 将保留的轮廓在原始图像上绘制出来for con in finalContours:cv2.drawContours(img, con[4], -1, (0, 0, 255), 3)return img, finalContoursdef dectshow(org_img, boxs):img = org_img.copy()for box in boxs:cv2.rectangle(img, (int(box[0]), int(box[1])), (int(box[2]), int(box[3])), (0, 255, 0), 2)x1 = box[0]y1 = box[1]x2 = box[2]y2 = box[3]cv2.circle(img, (x1, y1), 5, (0, 0, 255), -1)  # 红色圆点cv2.circle(img, (x2, y1), 5, (0, 255, 0), -1)  # 绿色圆点cv2.circle(img, (x2, y2), 5, (255, 0, 0), -1)  # 蓝色圆点point1 =  [x1, y1]point2 =  [x2, y1]point3 =  [x2, y2]width = math.sqrt((point2[0] - point1[0]) ** 2 + (point2[1] - point1[1]) ** 2)height = math.sqrt((point3[0] - point2[0]) ** 2 + (point3[1] - point2[1]) ** 2)width = width/3height = height/3# cv2.imshow('1', img)# 计算两点之间的距离print("宽 is:", width, "m")print("长 is:", height, "m")cv2.putText(img, f'W: {str(width)[:4] }mm H: {str(height)[:4]}mm', (int(box[0]), int(box[1]) - 40), cv2.FONT_HERSHEY_SIMPLEX, 0.5,(0, 255, 0), 2)cv2.imshow('dec_img', img)return img# 对角点排序函数
def reorder(myPoints):myPointsNew = np.zeros_like(myPoints)myPoints = myPoints.reshape((4, 2))add = myPoints.sum(1)myPointsNew[0] = myPoints[np.argmin(add)]myPointsNew[3] = myPoints[np.argmax(add)]diff = np.diff(myPoints, axis=1)myPointsNew[1] = myPoints[np.argmin(diff)]myPointsNew[2] = myPoints[np.argmax(diff)]return myPointsNew# 透视变换函数
def warpImg(img, points, w, h, pad=20):points = reorder(points)pts1 = np.float32(points)pts2 = np.float32([[0, 0], [w, 0], [0, h], [w, h]])matrix = cv2.getPerspectiveTransform(pts1, pts2)imgWarp = cv2.warpPerspective(img, matrix, (w, h))imgWarp = imgWarp[pad:imgWarp.shape[0] - pad, pad:imgWarp.shape[1] - pad]return imgWarp# 计算两点之间的距离
def findDis(pts1, pts2):return ((pts2[0] - pts1[0]) ** 2 + (pts2[1] - pts1[1]) ** 2) ** 0.5

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/103926.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Go语言入门心法(二): 结构体

Go语言入门心法(一) Go语言入门心法(二): 结构体 一: Go语言中结构体认知 go语言中的结构体认知升维:go语言中的结构体本身是一种自定义的数据类型,即然是数据类型,则可以用来声明其他的变量,被声明的变量即为结构体的实例对象go语言中的结构体融合了c语言中的结构体体征和面…

Xshell7和Xftp7超详细下载教程(包括安装及连接服务器附安装包)

1.下载 1.官网地址: XSHELL - NetSarang Website 选择学校免费版下载 2.将XSHELL和XFTP全都下载下来 2.安装 安装过程就是选择默认选项,然后无脑下一步 3.连接服务器 1.打开Xshell7,然后新建会话 2.填写相关信息 出现Connection establi…

JVM 性能调优参数

JVM分为堆内存和非堆内存 堆的内存分配用-Xms和-Xmx -Xms分配堆最小内存,默认为物理内存的1/64; -Xmx分配最大内存,默认为物理内存的1/4。 非堆内存分配用-XX:PermSize和-XX:MaxPermSize -XX:PermSize分配非堆最小内存,默认为物理…

【LeetCode高频SQL50题-基础版】打卡第5天:第26~30题

文章目录 【LeetCode高频SQL50题-基础版】打卡第5天:第26~30题⛅前言超过5名学生的课🔒题目🔑题解 求关注者的数量🔒题目🔑题解 只出现一次的最大数字🔒题目🔑题解 买下所有产品的客户&#x1f…

《进化优化》第4章 遗传算法的数学模型

文章目录 4.1 图式理论4.2 马尔可夫链4.3 进化算法的马尔可夫模型的符号4.4 遗传算法的马尔可夫模型4.4.1 选择4.4.2 变异4.4.3 交叉 4.5 遗传算法的动态系统模型4.5.1 选择4.5.2 变异4.5.3 交叉 4.1 图式理论 图式是描述一组个体的位模式,其中用*来表示不在乎的位…

如何在Ubuntu 20.04.6 LTS系统上运行Playwright自动化测试

写在前面 这里以 Ubuntu 20.04.6 LTS为例。示例代码:自动化测试代码。 如果过程中遇到其他非文本中提到的错误,可以使用搜索引擎搜索错误,找出解决方案,再逐步往下进行。 一、 环境准备 1.1 安装python3 1.1.1 使用APT安装Py…

python+opencv+深度学习实现二维码识别 计算机竞赛

0 前言 🔥 优质竞赛项目系列,今天要分享的是 🚩 pythonopencv深度学习实现二维码识别 🥇学长这里给一个题目综合评分(每项满分5分) 难度系数:3分工作量:3分创新点:3分 该项目较为新颖&…

跨语言深入探讨如何实现方法增强:Java Go的多策略实现

🌷🍁 博主猫头虎 带您 Go to New World.✨🍁 🦄 博客首页——猫头虎的博客🎐 🐳《面试题大全专栏》 文章图文并茂🦕生动形象🦖简单易学!欢迎大家来踩踩~🌺 &a…

虚拟现实VR技术在医疗行业的应用介绍

虚拟现实 (VR) 虽然经常与游戏联系在一起,但不可否认,未来科技少不了虚拟现实,其应用可以彻底改变许多行业。在医疗领域,无数人正在探索 VR 可以帮助患者和医疗从业者实现更好的治疗结果治疗方式,比如在手术、疼痛管理…

最新水果FL Studio21.2中文汉化版本覆盖升级

FLStudio中文21最新版本以其使用速度而闻名,是一个高度复杂的音乐制作环境。FL Studio免费,联合国音序器音频和MIDI每个复合编辑都是音乐。现代的DAW是一种非凡的野兽。首先,它在很大程度上把自己放在了(几乎)每个人记录过程的核心。其次&…

【计算机网络】——前言计算机网络发展的历程概述

主页点击直达:个人主页 我的小仓库:代码仓库 C语言偷着笑:C语言专栏 数据结构挨打小记:初阶数据结构专栏 Linux被操作记:Linux专栏 LeetCode刷题掉发记:LeetCode刷题 算法:算法专栏 C头…

【2023全网最全教程】web自动化测试入门

一、自动化测试基本介绍 1 自动化测试概述: 什么是自动化测试?一般说来所有能替代人工测试的方式都属于自动化测试,即通过工具和脚本来模拟人执行用例的过程。 2 自动化测试的作用 减少软件测试时间与成本改进软件质量通过扩大测试覆盖率…

hive 之select 中文乱码

此处的中文乱码和mysql的库表 编码 latin utf 无关。 直接上案例。 有时候我们需要自定义一列,有时是汉字有时是字母,结果遇到这种情况了。 说实话看到这真是糟心。这谁受得了。 单独select 没有任何问题。 这是怎么回事呢? 经过一番检查&…

【C++】-c++11的知识点(中)--lambda表达式,可变模板参数以及包装类(bind绑定)

💖作者:小树苗渴望变成参天大树🎈 🎉作者宣言:认真写好每一篇博客💤 🎊作者gitee:gitee✨ 💞作者专栏:C语言,数据结构初阶,Linux,C 动态规划算法🎄 如 果 你 …

十六、【橡皮擦工具组】

文章目录 橡皮擦背景橡皮擦1. 一次取样2. 连续取样3. 取样背景色板 魔术橡皮擦 橡皮擦 橡皮擦跟我们平常生活中所用的橡皮擦是一样,它是将图层的内容擦除,只剩下空白部分。另外当我们按住Alt的键去擦除空白部分的时候,也可以将背景的部分显示出来。 另…

深入解析Spring Cloud Gateway的GlobalFilter

文章目录 摘要引言GlobalFilter的作用使用GlobalFilter默认的GlobalFilter自定义GlobalFilter 示例代码配置GlobalFilter配置文件方式代码方式 高级用法:重写GlobalFilter思路代码实现 结论参考文献 摘要 本文将详细介绍Spring Cloud Gateway中的GlobalFilter&…

VR会议:远程带看功能,专为沉浸式云洽谈而生

随着科技的不断发展,VR技术已经成为当今市场上较为热门的新型技术之一了,而VR会议远程带看功能,更是为用户提供更加真实、自然的沉浸式体验。 随着5G技术的发展,传统的图文、视频这种展示形式已经无法满足消费者对信息真实性的需求…

Vue2 +Element UI 表格行合并

如果相邻数据是一致的&#xff0c;则单元格的行合并,指定需要合并的列&#xff0c;下面我是指定合并了分类和类型这两列。 先看效果 Element UI为我们的<el-table>提供了一个属性span-method&#xff1a;合并行或列的计算方法 下面是一个示例: html部分 - 主要是在表上指…

广州华锐互动:炼钢工厂VR仿真实训系统

随着科技的发展&#xff0c;我们的教育体系和职业培训方法也在迅速变化。其中&#xff0c;虚拟现实&#xff08;VR&#xff09;技术的出现为我们提供了一种全新的学习和培训方式。特别是在需要高度专业技能和安全性的领域&#xff0c;如钢铁冶炼。本文将探讨如何使用VR进行钢铁…

MySQL使用函数、存储过程实现:向数据表快速插入大量测试数据

实现数据表快速插入20W测试数据 实现过程创建表开启允许创建函数生成随机字符串生成随机整数生成随机地址创建存储过程调用存储过程查看插入数据 其他实用函数生成随机浮点数生成随机日期时间生成随机布尔值生成随机姓名生成随机手机号码生成随机邮箱地址生成随机IP地址生成随机…