基于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.rhkb.cn/news/368416.html

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

相关文章

马工程刑法期末复习笔记重点2

马工程刑法期末复习笔记重点2

【JavaWeb程序设计】环境配置和Web工程的创建

目录 一、安装JDK、Tomcat,进行测试Tomcat能否正常启动。 二、修改Tomcat端口为8976,重新进行测试 三、使用集成开发环境Intelligent Idea,绑定JDK和Tomcat,建立站点,并测试 四、编写一个简单的html页面&#xff0…

微信小程序遮罩层显示

效果展示&#xff1a; wxml页面&#xff1a; <view classmodal-mask wx:if{{showModal}}><view class"modal-container"><view classmodal-content></view><view classmodal-footer bindtap"closeImage">//这个/images/ind…

SpringMVC的架构有什么优势?——控制器(一)

文章目录 控制器(Controller)1. 控制器(Controller)&#xff1a;2. 请求映射(Request Mapping)&#xff1a;3. 参数绑定(Request Parameters Binding)&#xff1a;4. 视图解析器(View Resolver)&#xff1a;5. 数据绑定(Data Binding)&#xff1a;6. 表单验证(Form Validation)…

Workerman在线客服系统源码,附搭建教程

源码介绍&#xff1a; Workerman在线客服系统源码。 workerman是一个高性能的PHP socket 服务器框架&#xff0c;workerman基于PHP多进程以及libevent事件轮询库&#xff0c;PHP开发者只要实现一两个接口&#xff0c;便可以开发出自己的网络应用&#xff0c;例如Rpc服务、聊天…

leetCode.98. 验证二叉搜索树

leetCode.98. 验证二叉搜索树 题目描述 代码 /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(nullptr) {}* TreeNode(int x) : val(x), left(n…

秋招Java后端开发冲刺——并发篇2(JMM与锁机制)

本文对Java的内存管理模型、volatile关键字和锁机制进行详细阐述&#xff0c;包括synchronized关键字、Lock接口及其实现类ReentrantLock、AQS等的实现原理和常见方法。 一、JMM&#xff08;Java内存模型&#xff09; 1. 介绍 JMM定义了共享内存中多线程程序读写操作的行为规…

51单片机第18步_将TIM0用作13位定时器

本章重点学习将TIM0用作13位定时器。 1、定时器0工作在模式0框图 2、定时器0工作在模式0举例 1、Keil C51中有一些关键字&#xff0c;需要牢记&#xff1a; interrupt 0&#xff1a;指定当前函数为外部中断0&#xff1b; interrupt 1&#xff1a;指定当前函数为定时器0中断…

【C语言】union 关键字

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

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(…

克隆gitee仓库,在vs2022创建文件夹开发项目操作步骤

git网站 git知识大全 git教程&#xff1a;廖雪峰的官方网站 git菜鸟教程 gitee之创建项目步骤 同步源仓库 2. 克隆命令 3. 右击git Bash Here>粘贴命令行 4. 选中项目文件夹》创建本人文件夹&#xff08;ZYY&#xff09; 5. 打开vs2022》新建项目》选择Framework》下…

C++精解【10】

文章目录 读写文件概述example csv读文件读取每个字段读取机器学习数据库iris constexpr函数GMP大整数codeblock环境配置数据类型函数类 EigenminCoeff 和maxCoeffArray类 读写文件 概述 fstream typedef basic_fstream<char, char_traits<char>> fstream;此类型…

VSCode常用的一些插件

Chinese (Simplified) 汉语&#xff08;简体&#xff09;拓展包。 Auto Close Tag 可以自动增加xml/html的闭合标签。 CodeSnap 截图神器。截图效果在下面。 Dracula Official vscode一个很好看的主题。 Git Graph git管理工具。 GitHub Repositories 有了它&#xff0c;不…

前端利用vue如何实现导入和导出功能.md

1. 前端利用vue如何实现导入和到处功能 1.1. 导入功能&#xff08;以导入Excel文件为例&#xff09; 1.1.1. 实现步骤: 1.1.1.1. 安装依赖: 首先&#xff0c;你需要安装处理Excel文件的库&#xff0c;如xlsx。1.1.1.2. 创建上传组件: 使用Element UI的<el-upload>组件或其…

Qt:5.QWidget属性介绍(Enabled属性-控件可用性设置、geometry属性-控件位置/大小设置)

目录 一、 QWidget属性的介绍&#xff1a; 二、Enabled属性-控件可用性设置&#xff1a; 2.1Enabled属性的介绍&#xff1a; 2.2获取控件当前可用状态的api——isEnabled()&#xff1a; 2.3设置控件当前的可用状态的api—— setEnabled() &#xff1a; 2.4 实例&#xff…

git提交实战

以新项目为例&#xff0c;如何在新项目新分支提交代码。 1.查看文件所在位置 git init 2.克隆项目到本地并完成身份配置 3.将需要新增的文件放到指定目录路径下 4.进入新克隆的文件 cd XXX 5.切换分支 git checkout XXX 6.标红者即为新提交的文件 git status 7.加入 git …

Is ChatGPT a Good Personality Recognizer? A Preliminary Study?

ChatGPT是一个很好的人格识别者吗&#xff1f;初步调研 摘要1 介绍2 背景和相关工作3 实验3.1 数据集3.2 提示策略3.3 基线3.4 评估指标3.5 实现细节3.6 Overall Performance (RQ1)3.7 ChatGPT在人格识别上的公平性 (RQ2)3.8 ChatGPT对下游任务的人格识别能力&#xff08;RQ3&a…

linux——IPC 进程间通信

IPC 进程间通信 interprocess communicate IPC&#xff08;Inter-Process Communication&#xff09;&#xff0c;即进程间通信&#xff0c;其产生的原因主要可以归纳为以下几点&#xff1a; 进程空间的独立性 资源隔离&#xff1a;在现代操作系统中&#xff0c;每个进程都…

ValidateAntiForgeryToken、AntiForgeryToken 防止CSRF(跨网站请求伪造)

用途&#xff1a;防止CSRF&#xff08;跨网站请求伪造&#xff09;。 用法&#xff1a;在View->Form表单中: aspx&#xff1a;<%:Html.AntiForgeryToken()%> razor&#xff1a;Html.AntiForgeryToken() 在Controller->Action动作上&#xff1a;[ValidateAntiForge…

SSM少儿读者交流系-计算机毕业设计源码20005

摘要 随着信息技术的发展和互联网的普及&#xff0c;少儿读者之间的交流方式发生了革命性的变化。通过使用Java编程语言&#xff0c;可以实现系统的高度灵活性和可扩展性。而SSM框架的采用&#xff0c;可以提供良好的开发结构和代码管理&#xff0c;使系统更加稳定和易于维护。…