基于opencv的斜光测距及python实现

1.前言

最近做了一个基于opencv的斜光测距的小项目,东西不多,但是很有意思,值得拿出来学一学。项目里面需要比较精确的定位功能,将前人matlab代码移植到python上,并且做了一些优化,简化逻辑(毕竟我是专业的程序员),也用了tkinter界面包装了一下,最后通过pyinstaller打包成程序给同事使用。

2.原理

在这里插入图片描述

通过使用不同的亮点位置和对应的高度进行多元线性回归建模,再对新的亮点位置进行高度预测。

在这里插入图片描述

如图分别是14,14.5,15,15.5对应的四张光点位置图。

3.获取亮点位置

def get_box(image):# 将图像转换为灰度图像gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)# 应用高斯模糊来减少噪声blurred = cv2.GaussianBlur(gray, (5, 5), 0)max_val = np.max(blurred)_, binary = cv2.threshold(blurred, max_val/2, 255, cv2.THRESH_BINARY)# 形态学开运算去除噪声kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5))opened = cv2.morphologyEx(binary, cv2.MORPH_OPEN, kernel)# 找到轮廓contours, _ = cv2.findContours(opened, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)# 如果找到轮廓,计算质心if contours:largest_contour = max(contours, key=cv2.contourArea)M = cv2.moments(largest_contour)if M["m00"] != 0:cx = int(M["m10"] / M["m00"])cy = int(M["m01"] / M["m00"])else:cx, cy = 0, 0centroid = (cx, cy)# 计算边界框x, y, w, h = cv2.boundingRect(largest_contour)p=10bbox = (x-p, y-p, w+2*p, h+2*p)# 在图像上绘制质心和边界框output_image = image.copy()cv2.circle(output_image, centroid, 5, (0, 255, 0), -1)x,y,w,h=bboxcv2.rectangle(output_image, (x, y), (x + w, y + h), (0, 255, 0), 2)print(f"亮点的中心位置: {centroid},亮点的边界框: {bbox}")return centroid,bbox,output_imageelse:return None

4.建模

不想再安装其它的python包了,就基于numpy写的LineRegression。

class LinearRegression:def __init__(self):self.theta = Nonedef fit(self, X, y):"""训练线性回归模型参数:X:自变量数据,形状为 (m, n),其中 m 是样本数量,n 是特征数量y:因变量数据,形状为 (m, 1)"""# 在 X 前面加一列1,以便于计算截距项X_b = np.c_[np.ones((X.shape[0], 1)), X]# 使用正规方程求解回归系数self.theta = np.linalg.inv(X_b.T @ X_b) @ X_b.T @ ydef predict(self, X):"""对新样本进行预测参数:X:自变量数据,形状为 (m, n),其中 m 是样本数量,n 是特征数量返回值:y_pred:预测的因变量数据,形状为 (m, 1)"""if self.theta is None:raise ValueError("模型未经过训练,请先调用 fit 方法")# 在 X 前面加一列1,以便于计算截距项X_b = np.c_[np.ones((X.shape[0], 1)), X]# 使用训练得到的回归系数进行预测y_pred = X_b @ self.thetareturn y_pred

建模效果
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

5.全部代码

项目地址:https://gitee.com/zhang_jie_sc/auto-focus

import re
import cv2
import numpy as np
import osfrom matplotlib import pyplot as pltdef get_box(image):# 将图像转换为灰度图像gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)# 应用高斯模糊来减少噪声blurred = cv2.GaussianBlur(gray, (5, 5), 0)max_val = np.max(blurred)_, binary = cv2.threshold(blurred, max_val/2, 255, cv2.THRESH_BINARY)# 形态学开运算去除噪声kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5))opened = cv2.morphologyEx(binary, cv2.MORPH_OPEN, kernel)# 找到轮廓contours, _ = cv2.findContours(opened, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)# 如果找到轮廓,计算质心if contours:largest_contour = max(contours, key=cv2.contourArea)M = cv2.moments(largest_contour)if M["m00"] != 0:cx = int(M["m10"] / M["m00"])cy = int(M["m01"] / M["m00"])else:cx, cy = 0, 0centroid = (cx, cy)# 计算边界框x, y, w, h = cv2.boundingRect(largest_contour)p=10bbox = (x-p, y-p, w+2*p, h+2*p)# 在图像上绘制质心和边界框output_image = image.copy()cv2.circle(output_image, centroid, 5, (0, 255, 0), -1)x,y,w,h=bboxcv2.rectangle(output_image, (x, y), (x + w, y + h), (0, 255, 0), 2)print(f"亮点的中心位置: {centroid},亮点的边界框: {bbox}")return centroid,bbox,output_imageelse:return Nonedef get_files(dir):img_path_list = [f for f in os.listdir(dir) iff.startswith('Point') and f.endswith('.jpg')]  # 获取该文件夹中所有jpg格式的图像val_list=[]for p in img_path_list:# 使用正则表达式匹配_后.前的0或0.5match = re.search(r'_(\d+(\.\d+)?)\.', p)if match:val=match.group(1)val_list.append(float(val))else:raise ValueError('{0}文件名错误,无法提取位置i学那些'.format(p))return img_path_list,val_listdef merge_intersecting_boxes(boxes):merged_boxes = []# 计算包含所有框的大框x_min = min(box[0] for box in boxes)y_min = min(box[1] for box in boxes)x_max = max(box[0] + box[2] for box in boxes)y_max = max(box[1] + box[3] for box in boxes)big_box = (x_min, y_min, x_max - x_min, y_max - y_min)# 返回大框和空的合并框列表return big_box, merged_boxesdef r2_score(y_true,y_pred):# 计算相关系数corr = np.corrcoef(y_true, y_pred)[0, 1]# 计算 R 方值r2 = corr ** 2return r2def plot_image_and_r2_zzz(image, x, y,r2,theta):# 将 BGR 格式转换为 RGB 格式image = cv2.cvtColor(image.copy(), cv2.COLOR_BGR2RGB)# 创建一个图形和两个子图fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(10, 5), gridspec_kw={'top': 0.85})# 设置窗口标题方式二fig.canvas.manager.window.title("建模结果")# 在第一个子图中显示图片ax1.imshow(image)ax1.axis('off')ax1.set_title('Box')# 在第二个子图中显示拟合直线ax2.plot(x, y, 'o', label='Data')ax2.plot(x, x, label='Fitted Line')# 将每个数字转换为字符串,保留五位小数theta_str = "(k1={:.4f}, k2={:.4f}, b={:.4f})".format(*theta)ax2.set_title('Fitted Line (theta={}, r2={:.5f})'.format(theta_str,r2))# 添加轴标签ax2.set_xlabel('y_true')ax2.set_ylabel('y_pred')ax2.legend()# 显示图形plt.tight_layout()plt.show()class LinearRegression:def __init__(self):self.theta = Nonedef fit(self, X, y):"""训练线性回归模型参数:X:自变量数据,形状为 (m, n),其中 m 是样本数量,n 是特征数量y:因变量数据,形状为 (m, 1)"""# 在 X 前面加一列1,以便于计算截距项X_b = np.c_[np.ones((X.shape[0], 1)), X]# 使用正规方程求解回归系数self.theta = np.linalg.inv(X_b.T @ X_b) @ X_b.T @ ydef predict(self, X):"""对新样本进行预测参数:X:自变量数据,形状为 (m, n),其中 m 是样本数量,n 是特征数量返回值:y_pred:预测的因变量数据,形状为 (m, 1)"""if self.theta is None:raise ValueError("模型未经过训练,请先调用 fit 方法")# 在 X 前面加一列1,以便于计算截距项X_b = np.c_[np.ones((X.shape[0], 1)), X]# 使用训练得到的回归系数进行预测y_pred = X_b @ self.thetareturn y_predif __name__=='__main__':file_dir="./20240531_113524"img_path_list, locs = get_files(file_dir)coors = []boxs = []for i, image_name in enumerate(img_path_list):  # 逐一读取图像item = cv2.imread(os.path.join(file_dir, image_name))cneter, box, _ = get_box(item)coors.append(list(cneter))boxs.append(box)merge_box, _ = merge_intersecting_boxes(boxs)# 使用线性回归拟合数据matx = np.array(coors)arr_x = matx[:, 0]reg = LinearRegression()reg.fit(matx, locs)y_true = np.array(locs)y_pred = reg.predict(matx)r2 = r2_score(y_true, y_pred)# 输出 R^2 值draw_img = cv2.imread(os.path.join(file_dir, img_path_list[0]), cv2.IMREAD_COLOR)x, y, w, h = merge_boxcv2.rectangle(draw_img, (x, y), (x + w, y + h), (0, 255, 0), 2)plot_image_and_r2_zzz(draw_img, y_true, y_pred, r2, reg.theta)

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

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

相关文章

pandas数据分析(7)

组合DataFrame 连接 如果只是要将多个DataFrame粘合在一起,那么concat函数是最佳选择。在默认情况下,concat会将DataFrame按行粘合在一起,同时会将各列自动对齐。 如果想要按列进行粘合,需要将axis设置为1: concat的特…

制造企业真的需要数字化转型吗?一文讲透:为何做,如何做?

此前拜访了不少制造企业,其以中小型企业居多,在与企业负责人交流数字化转型话题时,感触最多的还是管理者对“数字化转型”的认知。 在数字化转型方面从国家层面到地方政府进行大量的宣传与政策支持,部分行业头部企业也从数字化转…

百度出品_文心快码Comate提升程序猿效率

1.文心快码 文心快码包含指令、插件 和 知识三种功能, 1)指令包含Base64编码、Base64解码、JSON转TS类型、JSON转YAML、JWT解码喂JSON。 2)插件包含 3)指令包含如下功能: 官网链接

AI墓地:738个倒闭AI项目的启示

近年来,人工智能技术迅猛发展,然而,不少AI项目却在市场上悄然消失。根据AI工具聚合网站“DANG”的统计,截至2024年6月,共有738个AI项目停运或停止维护。本文将探讨这些AI项目失败的原因,并分析当前AI初创企…

C语言:结构体数组

结构体数组 介绍定义结构体定义结构体数组初始化结构体数组访问和修改结构体数组的元素遍历结构体数组 示例高级用法动态分配结构体数组使用 malloc 动态分配使用 calloc 动态分配 结构体数组作为函数参数结构体数组与指针多维结构体数组使用 typedef 简化结构体定义结构体数组…

ClickHouse概述

ClickHouse概述 文章目录 ClickHouse概述ClickHouse是什么ClickHouse快的理由什么是OLAPClickHouse的特点列式存储DBMS 的功能多样化引擎高吞吐写入能力数据分区与线程级并行 ClickHouse的应用合适场景不适合场景 ClickHouse是什么 ClickHouse 是俄罗斯的 Yandex 于 2016 年开…

ubuntu20.04配置调试工具

1.准备工作&#xff1a;安装g或者gdb sudo apt updatesudo apt install gg --versionsudo apt install gdbgdb --version 2.配置环境 2.1在本地新建一个main.cpp #include <iostream> #include <vector> #include <string>using namespace std;int main(…

MySQL资讯|2024年MySQL第一个长期支持版本8.4发布

&#x1f4eb; 作者简介&#xff1a;「六月暴雪飞梨花」&#xff0c;专注于研究Java&#xff0c;就职于科技型公司后端工程师 &#x1f3c6; 近期荣誉&#xff1a;华为云云享专家、阿里云专家博主、腾讯云优秀创作者、ACDU成员 &#x1f525; 三连支持&#xff1a;欢迎 ❤️关注…

【漏洞复现】Emlog Pro 2.3.4——任意用户登入、会话持久化(CVE-2024-5044)

声明&#xff1a;本文档或演示材料仅供教育和教学目的使用&#xff0c;任何个人或组织使用本文档中的信息进行非法活动&#xff0c;均与本文档的作者或发布者无关。 文章目录 漏洞描述漏洞复现 漏洞描述 漏洞编号&#xff1a;CVE-2024-5044 漏洞成因&#xff1a; 在Emlog Pro …

黑马点评DAY5|商户查询缓存

商户查询缓存 缓存的定义 缓存就是数据交换的缓冲区&#xff08;Cache&#xff09;&#xff0c;是存储数据的临时地方&#xff0c;一般读写性能较高。 比如计算机的CPU计算速度非常快&#xff0c;但是需要先从内存中读取数据再放入CPU的寄存器中进行运算&#xff0c;这样会限…

【C语言】union 关键字

在C语言中&#xff0c;union关键字用于定义联合体。联合体是一种特殊的数据结构&#xff0c;它允许不同的数据类型共享同一段内存。所有联合体成员共享同一个内存位置&#xff0c;因此联合体的大小取决于其最大成员的大小。 定义和使用联合体 基本定义 定义一个联合体类型时…

SiCat:一款多功能漏洞利用管理与搜索工具

关于SiCat SiCat是一款多功能漏洞利用管理与搜索工具&#xff0c;该工具基于纯Python 3开发&#xff0c;旨在帮助广大研究人员有效地识别和收集来自开源和本地存储库的漏洞信息。 SiCat专注于网络安全管理方面的实践工作&#xff0c;允许研究人员快速实现在线搜索&#xff0c;…

2024亚太赛(中文赛)数学建模竞赛选题建议+初步分析

提示&#xff1a;DS C君认为的难度&#xff1a;B<C<A&#xff0c;开放度&#xff1a;C<A<B。 综合评价来看 A题适合有较强计算几何和优化能力的团队&#xff0c;难度较高&#xff0c;但适用面较窄。 B题数据处理和分析为主&#xff0c;适合数据科学背景的团队…

Android TextView的属性与用法

文本控件包括TextView、EditText、AutoCompleteTextView、CheckedTextView、MultiAutoCompleteTextView、TextInputLayout等&#xff0c;其中TextView、EditText是最基本最重要的文本控件&#xff0c;是必须要掌握的文本控件。 1.TextView TextView控件用于显示文本信息&…

自然语言处理学习--3

对自然语言处理领域相关文献进行梳理和总结&#xff0c;对学习的文献进行梳理和学习记录。希望和感兴趣的小伙伴们一起学习。欢迎大家在评论区进行学习交流&#xff01; 论文&#xff1a;《ChineseBERT: Chinese Pretraining Enhanced by Glyph and Pinyin Information》 下面…

原厂商是什么意思?云管平台原厂商有哪些企业?

最近不少IT小伙伴在问关于原厂商相关问题&#xff0c;今天我们就来简单回答一下&#xff0c;仅供参考&#xff01; 原厂商是什么意思&#xff1f; 原厂商&#xff0c;或称原厂&#xff0c;是指生产特定产品或零部件的原始厂家。 软件原厂商是什么意思&#xff1f; 软件原厂…

QT截屏,截取控件为图片,指定范围截屏三种截屏方式

项目中我们常用到截取屏幕&#xff0c;Qt给我的们多种方式&#xff1a; 主要有以下三种&#xff1a; 截取全屏&#xff1b;截取控件为图片&#xff1b;指定位置截屏三种截屏方式&#xff1b; 1.截取全屏 常用&#xff1a; 实现&#xff1a; QScreen *screen QGuiApplicat…

数据结构(一)C语言补

数据结构 内存空间划分 一个进程启动后&#xff0c;会生成4G的内存空间 0~3G是用户空间(应用层) 3~4G是内核空间(底层) 0~3G 3~4G 所有的进程都会共享3G~4G的内核空间&#xff0c; 但是每个进程会独立拥有0~3G的用户空间。 栈区 存放数据特点 栈区存放数据的申请空间的先后…

面试篇-Redis-2+持久化+过期key删除+内存淘汰

文章目录 前言一、你知道Redis 数据是怎么持久化的1.1 Redis 持久化的方式Rdb&#xff1a;1.1.1 主动备份save 命令&#xff1a;1.1.2 Redis 中使用bgsave 进行Rdb 的持久化 &#xff1a; 1.2 Redis 持久化的方式Aof&#xff1a;1.2.1 使用AOF 模式进行数据存储&#xff1a;1.2…

明星代言方式8种助力品牌占领市场-华媒舍

1. 明星代言的重要性和市场价值 明星代言是一种常见的品牌推广方式&#xff0c;通过联系知名度高的明星来推广产品或服务&#xff0c;从而提升品牌的知名度和美誉度。明星代言能够借助明星的影响力和粉丝基础&#xff0c;将品牌信息传达给更广泛的受众&#xff0c;从而提高销量…