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

news2024/12/23 14:46:41

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, 0
        centroid = (cx, cy)
        # 计算边界框
        x, y, w, h = cv2.boundingRect(largest_contour)
        p=10
        bbox = (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=bbox
        cv2.rectangle(output_image, (x, y), (x + w, y + h), (0, 255, 0), 2)
        print(f"亮点的中心位置: {centroid},亮点的边界框: {bbox}")
        return centroid,bbox,output_image
    else:
        return None

4.建模

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

class LinearRegression:
    def __init__(self):
        self.theta = None

    def 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 @ y

    def 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.theta

        return y_pred

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

5.全部代码

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

import re
import cv2
import numpy as np
import os

from matplotlib import pyplot as plt


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, 0
        centroid = (cx, cy)
        # 计算边界框
        x, y, w, h = cv2.boundingRect(largest_contour)
        p=10
        bbox = (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=bbox
        cv2.rectangle(output_image, (x, y), (x + w, y + h), (0, 255, 0), 2)
        print(f"亮点的中心位置: {centroid},亮点的边界框: {bbox}")
        return centroid,bbox,output_image
    else:
        return None

def get_files(dir):
    img_path_list = [f for f in os.listdir(dir) if
                     f.startswith('Point') and f.endswith('.jpg')]  # 获取该文件夹中所有jpg格式的图像
    val_list=[]
    for p in img_path_list:
        # 使用正则表达式匹配_后.前的0或0.5
        match = 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_list

def 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_boxes

def r2_score(y_true,y_pred):
    # 计算相关系数
    corr = np.corrcoef(y_true, y_pred)[0, 1]
    # 计算 R 方值
    r2 = corr ** 2
    return r2

def 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 = None

    def 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 @ y

    def 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.theta

        return y_pred

if __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_box
    cv2.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.coloradmin.cn/o/1893765.html

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

相关文章

Spring Boot中使用SpringEvent组件

Spring的事件机制是基于观察者模式的实现,主要由以下三个部分组成: 事件(Event):事件是应用中发生的重要事情,通常是一个继承自ApplicationEvent的类。 事件发布器(Publisher)&…

iPhone白苹果怎么修复?4个方法解决你的烦恼!

其实iPhone手机出现“白苹果”这事,如果是iPhone轻度用户,可能大家一辈子都不会遇到一次。但如果是iPhone重度用户、越狱爱好者、软件收集狂,可能就会遇到了。 白苹果,一般指iOS设备出现软、硬件故障,卡在一个类似于启…

AI智能对话绘画音乐三合一创作神器源码系统 带完整的源代码包以及搭建部署教程

系统概述 该系统旨在通过先进的AI技术,实现用户与机器的深度交互,从而在对话中创作出独一无二的艺术作品——无论是细腻的画作、动人的乐曲,还是两者兼备的多媒体体验,都能在这个平台上轻松实现。本文将详细介绍该系统的系统概述…

2024年在WordPress中创建销售活动的专家级优惠券方法

2024年在WordPress中创建销售活动的专家级优惠券方法 今天我想和大家分享一些关于如何在WordPress网站上使用专家级优惠券工具来创建销售活动的经验。对于已经在电商领域有一定经验的店主,利用专家级优惠券不仅能吸引顾客,还能显著增加销量。在这篇文章…

CLAM用于弱监督WSI分析

计算病理学(computational pathology)下的深度学习方法需要手动注释大型 WSI 数据集,并且通常存在领域适应性和可解释性较差的问题。作者报告了一种可解释的弱监督深度学习方法,只需要WSI级标签。将该方法命名为聚类约束注意力多实…

商务视频推广8个增加用户转化率的技巧-华媒舍

商务视频推广是一种有效的营销策略,可以帮助企业吸引更多的潜在客户并增加用户转化率。我们将介绍8个提高商务视频推广效果的技巧,帮助您更好地利用视频来促进业务增长。 技巧一:制作高质量的内容 成功的商务视频推广首先要有高质量的内容。…

达梦数据库 页大小与数据库字段长度的关系

对于达梦数据库实例而言,页大小 (page_size)、簇大小 (extent_size)、大小写敏感 (case_sensitive)、字符集 (charset) 这四个参数,一旦确定无法修改;如果过程中发现这些数据设置的不对,只能是重新新建数据库实例,而不…

Linux服务器上安装CUDA11.2和对应的cuDNN 8.4.0

一、检查 检查本机是否有CUDA工具包,输入nvcc -V: 如图所示,服务器上有CUDA,但版本为9.1.85,版本过低,因此博主要重装一个新的。 二、安装CUDA 1.查看服务器最高支持的CUDA版本 在命令行输入nvidia-smi查看显卡驱动…

航空数据管控系统-①项目准备阶段:任务2:项目技术预研(技术架构)

任务描述 掌握项目的总体功能,及实现流程。预习项目中所使用到的技术和知识点。 任务指导 一、项目效果展示 图1-数据统计大屏页面 图2-航空实时监控页面 二、项目架构 1、总体架构: 2、技术架构 技术清单: 功能 组件 说明 消息中间件…

MySQL 三大日志 ( binlog、redo log 和 undo log ) 的作用?

MySQL是一个功能强大的关系型数据库管理系统,它的高可靠性、高性能和易用性使得它成为众多企业和开发者的首选。在MySQL内部,为了保证数据的完整性、恢复能力和并发性能,设计了一套复杂的日志系统。其中,redo log、bin log和undo …

数据开发人员如何真正理解业务、并构建业务模型?

问题背景 最近有同学在问,新到一家公司,如何去深入理解业务?并高于业务视角呢? 针对这个问题 ,我们将问题进行拆分以下几点进行回答,首先懂业务的标准是什么? 根据笔者的经验将懂业务标准进行如…

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

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

2024最全前端面试系列(计算机网络)(非科班出身最薄弱的环节)

2020最全前端面试系列(CSS) 2020最全前端面试系列(VUE) 2020最全前端面试系列(浏览器原理) 2020最全前端面试系列(数据结构) 常见状态码 | | 类别 | 原因短语 | | — | — | —…

Laravel 谨慎使用Storage::append()

在 driver 为 local 时,Storage::append()在高并发下,会存在丢失数据问题,文件被覆写,而非尾部添加,如果明确是本地文件操作,像日志写入,建议使用 Illuminate\Filesystem\Filesystem或者php原生…

window下git bash设置启动后默认路径进入自己的工程

方法一:更改快捷方式 方法二:修改~/.bashrc

香港即将“放松”加密货币监管!加密牌照制度备受批评!全球主力军无法进入香港市场?动摇了香港Web3的信心!

2024年7月3日,香港金融服务及库务局局长许正宇在立法会会议上表示,香港金融管理局(HKMA)和证券及期货事务监察委员会(SFC)将根据市场发展情况,适时检讨虚拟资产相关活动的监管要求。 这一表态引发了人们对香港加密货币监管框架可能进行调整的…

Android Studio 大作业--学生信息管理系统

欢迎光临: 古之立大事者,不惟有超世之才,亦必有坚忍不拔之志。——苏轼 ---------------🍎------------🍉-------------- 🐼学编程的bird的博客,邀您一起学习🦌 ----------------&am…

面试篇-Redis-3+分布式锁+集群部署

文章目录 前言一、你们项目中使用Redis 作为分布式锁吗1.1 将余券存入到Redis 中,当有人抢券进行-1操作并存回:1.2 分布式锁的使用1.3 Redis 分布式锁是怎么实现的:1.4 Redisson 分布式锁是可重入的吗:1.5 Redis 出现脑裂时如何保…

Java项目:基于SSM框架实现的班主任助理管理系统【ssm+B/S架构+源码+数据库+开题报告+毕业论文】

一、项目简介 本项目是一套基于SSM框架实现的班主任助理管理系统 包含:项目源码、数据库脚本等,该项目附带全部源码可作为毕设使用。 项目都经过严格调试,eclipse或者idea 确保可以运行! 该系统功能完善、界面美观、操作简单、功…

防水头灯在户外探险的应用_鼎跃安全

随着我国民众生活品质的显著提升,人们对户外探险的热爱与参与度也日益高涨。在这一充满挑战与未知的旅途中,拥有一件可靠的照明设备成为了确保安全与探索乐趣的关键。面对户外多变的自然环境,包括突如其来的降雨、潮湿的森林小径等恶劣条件&a…