图像处理之SVD检测显示屏缺陷(C++)

news2025/1/12 1:47:58

图像处理之SVD检测显示屏缺陷(C++)


文章目录

  • 图像处理之SVD检测显示屏缺陷(C++)
  • 前言
  • 一、SVD算法简介
  • 二、代码实现
  • 总结


前言

显示屏缺陷检测是机器视觉领域的一处较广泛的应用场景,显示屏主要有LCD和OLED,缺陷类型主要包括点线缺陷(亮暗点,亮暗线),Mura缺陷(亮度显示不均),外观缺陷(划伤,破损,脏污)等。

SVD(奇异值分解)算法主要用于图像的降维和重构,图像重构一般是取前k个较大的奇异值,其他值置为0,滤除干扰噪声从而实现图像重构;而论文作者反其道而行,令前k个奇异值为0进行图像重构,用于凸显图片中的各类缺陷,达到缺陷检测的目的。

根据SVD的算法原理,较大奇异值包含图像主要特征,而较小奇异值包含噪声信息,在实验中发现,重构图片中,除了凸显出Mura缺陷外,还包含很多雪花状噪声;随着k值的增大,当k值超过一个阈值后,重构图片中Mura缺陷将会消失;故,我们可以将奇异值矩阵分为3部分:包含图像主要特征的较大奇异值,包含缺陷特征的相对较大奇异值,包含噪声特征的较小奇异值,将较大奇异值和较小奇异值都置零,只保留相对较大奇异值,以此重构图像,在图像缺陷信息基础上同时做去噪处理。

参考资料:
Lu, CJ., Tsai, DM. Automatic defect inspection for LCDs using singular value decomposition. AMT 25, 53–61 (2005). https://doi.org/10.1007/s00170-003-1832-6
反向应用SVD(奇异值分解)算法检测显示屏缺陷
反向应用SVD(奇异值分解)算法检测显示屏缺陷(续)


一、SVD算法简介

一整张图片就是一个像素值矩阵,每个像素值0-255之间,SVD可以把一个矩阵分解成左奇异向量矩阵U、奇异值矩阵 Σ(S)和右奇异向量矩阵VT
奇异值分解
正交矩阵U:m行m列,该矩阵的每一个列向量都是AAT的特征向量;
正交矩阵VT:n行n列,该矩阵的每一个列向量都是ATA的特征向量;
对角阵Σ:m行n列,将ATA或AAT的特征值开根号,得到的就是该矩阵主对角线上的元素,也可以看成矩阵A的奇异值。

二、代码实现

#include <iostream>
#include <opencv.hpp>
using namespace std;
using namespace cv;

#define R 0.3
#define G -0.03

/*
* @param cv::Mat S	 特征值集合
* @param int	 k	 上限
* @param int	 l	 下限
* @brief 根据经验公式计算k和l
*/
void get_k_l(const cv::Mat& S, int& k, int& l)
{
	cv::Mat S_ = S.clone();
	//求特征值的平均值和方差
	cv::Mat meanMat, stdMat;
	cv::meanStdDev(S, meanMat, stdMat);

	for (int i = 0; i < S.rows; i++)
	{
		S_.at<float>(i, 0) = (S_.at<float>(i, 0) - meanMat.at<double>(0)) / stdMat.at<double>(0);
	}

	//计算k
	for (int i = 0; i < S.rows; i++)
	{
		if (S_.at<float>(i, 0) < R)
		{
			k = i;
			break;
		}
	}

	//计算g
	for (int i = 0; i < S.rows; i++)
	{
		if (S_.at<float>(i, 0) < G)
		{
			l = i;
			break;
		}
	}
}

/*
* @param cv::Mat src 输入图像(单通道灰度图像)
* @param cv::Mat dst 输出图像
* @param int	 k	 上限
* @param int	 l	 下限
* @param bool 	 cal	true--自动计算,只需修改G\R;false--手动指定k和l
* @brief svd分解
*/
void svd(const cv::Mat& src, cv::Mat& dst,int k,int l,bool cal)
{
	cv::Mat src_ = src.clone();
	src_.convertTo(src_, CV_32FC1);
	cv::Mat U, S, Vt;
	cv::SVD::compute(src_, S, U, Vt);	//SVD分解
	// S是n行1列(CV_32F);U是m行n列(CV_32F);Vt是n行n列(CV_32F)

	//自动计算
	if(cal) get_k_l(S, k, l);
	if (k < 0)
	{
		cout << "k should larger than 0";
		return;
	}

	if (l <= k)
	{
		cout << "l should larger than k";
		return;
	}

	int min_dim = min(src.rows, src.cols);

	cv::Mat S_(min_dim, min_dim, CV_32FC1, cv::Scalar(0));
	for (int i = k; i <= l; i++)
	{
		S_.at<float>(i, i) = S.at<float>(i, 0);
	}

	cv::Mat result = U * S_ * Vt;
	result.convertTo(dst, CV_8UC1);
}

int main()
{
	string path = "F://work_study//algorithm_demo//";
	cv::Mat src = cv::imread(path + "lena.jpg", cv::IMREAD_GRAYSCALE);
	if (src.empty())
		return -1;


	cv::Mat dst;
	svd(src, dst, 10, 20,true);

	imshow("dst", dst);
	cv::waitKey(0);
	return 0;
}

lena
svd


总结

本文主要介绍了SVD分解在图像重构、缺陷检测的应用,使用C++基于OpenCV库实现。
对于奇异值,它跟我们特征分解中的特征值类似,在奇异值矩阵中也是按照从大到小排列,而且奇异值的减少特别的快,在很多情况下,前10%甚至1%的奇异值的和就占了全部的奇异值之和的99%以上的比例。我们也可以用最大的k个的奇异值和对应的左右奇异向量来近似描述矩阵。
该算法的特征值性质有点类似频率域的高频、低频、中频等,欢迎大家交流。
本文代码均在本地运行成功,有问题多交流。

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

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

相关文章

4.5_shell的执行流控制

##1.for语句## &#xff08;1&#xff09;for语句作用 为循环执行动作 &#xff08;2&#xff09;for语句结构 for 定义变量 do 使用变量&#xff0c;执行动作 done 结束标志 &#xff08;3&#xff09;for语句的基本格式 格式1 格式1&#xff1a;#!/b…

现身说法暑期三下乡社会实践团一个好的投稿方法胜似千军万马

作为一名在校大学生,去年夏天我有幸参与了学院组织的暑期大学生三下乡社会实践活动,这段经历不仅让我深入基层,体验了不一样的生活,更是在新闻投稿的实践中,经历了一次从传统到智能的跨越。回忆起那段时光,从最初的邮箱投稿困境,到后来智慧软文发布系统的高效运用,每一步都刻印…

(六)JSP教程——out对象

out对象是在JSP中经常使用到的对象&#xff0c;它本质上是一个输出流&#xff0c;前面已经多次使用&#xff0c;我们经常使用它的print()和println()方法&#xff0c;这些方法主要用于实现客户端数据的输出。通过out对象也可以直接向客户端发送一个由程序动态生成的HTML文件。 …

PPPoE实验新手必备:从0到1的网络配置指南!

5月18日&#xff0c;思科华为初级网工课程&#xff0c;等你免费试听 V&#xff1a;glab-mary 今天带大家学习一下华为PPPoE实验配置 01、实验拓扑 02、实验需求 1.完成PPP封装 2.完成PPP的PAP验证 3.完成PPP的CHAP验证 4.完成R1和R2之间的PPPOE 03、实验步骤 a . PPP封…

内存卡罢工,数据危机?别急,有救!

在日常生活和工作中&#xff0c;我们越来越依赖于各种电子设备来存储重要数据。其中&#xff0c;内存卡因其便携性和大容量而广受欢迎。然而&#xff0c;当内存卡突然损坏打不开时&#xff0c;我们该如何应对&#xff1f;本文将为您详细解析这一问题&#xff0c;并提供有效的解…

c语言实现贪吃蛇小游戏————附全代码!!!

目录 1.Win32 API 1.1控制台应用程序 1.2控制台的名称&#xff0c;控制台窗口大小 1.3设置控制台光标位置 COORD - 光标坐标 GetStdHandle - 获取句柄 SetConsoleCursorPosition - 设置光标位置 封装一个设置光标的函数 1.4设置控制台光标的属性 CONSOLE_CURSOR_INFO …

Cargo - 构建 rust项目、管理依赖包

文章目录 关于 Cargo构建项目创建工程编译运行buildclean 管理依赖添加依赖updatecheck计时 manual rust 安装可参考&#xff1a;https://blog.csdn.net/lovechris00/article/details/124808034 关于 Cargo Cargo 官方文档 &#xff1a; https://doc.rust-lang.org/cargo/crat…

泛型编程四:容器

文章目录 前言一、序列容器verctor 总结 前言 STL有六大部件&#xff0c;容器、算法、仿函数、迭代器、适配器和分配器。除了算法是函数模板&#xff0c;其他都是类模板。容器可以分为序列容器和关联容器。常见的序列容器有vector、array、deque、list、forward-list&#xff…

;【排列【

c语言中的小小白-CSDN博客c语言中的小小白关注算法,c,c语言,贪心算法,链表,mysql,动态规划,后端,线性回归,数据结构,排序算法领域.https://blog.csdn.net/bhbcdxb123?spm1001.2014.3001.5343 给大家分享一句我很喜欢我话&#xff1a; 知不足而奋进&#xff0c;望远山而前行&am…

【Kolmogorov-Arnold网络 替代多层感知机MLPs】KAN: Kolmogorov-Arnold Networks

KAN: Kolmogorov-Arnold Networks 论文地址 代码地址 知乎上的讨论&#xff08;看一下评论区更正&#xff09; Abstract Inspired by the Kolmogorov-Arnold representation theorem, we propose Kolmogorov-Arnold Networks (KANs) as promising alternatives to Multi-Layer…

1.使用uniapp搭建微信小程序项目并引入前端组件资源

文章目录 1. 项目配置1.1. 新建vue3项目1.2. 关联云空间1.3. 运行到微信开发者工具 2. 前端组件2.1. uniCloud的内置组件和扩展组件2.2. uView3.02.3. 在uniapp项目引入uview3 1. 项目配置 1.1. 新建vue3项目 由于我们要使用vue3而不是vue2&#xff0c;所以要选好版本&#x…

移动端底层事件(如左滑返回事件)在同一个路由下不同页面需要不同的处理要怎样才能做到统一处理?

目录 一、问题 二、解决方法 三、总结 tiips:如嫌繁琐&#xff0c;直接移步总结即可&#xff01; 一、问题 1.测试提了个bug:进入了一个模块A里面的子页面 a1,左滑后按照用户预期应该是返回到模块A,结果回到了app首页。 二、解决方法 1.一开始&#xff1a;啊&#xff0c;…

分布式与一致性协议之ZAB协议(七)

ZAB协议 ZAB协议:如何处理读写请求 你应该有这样的体会&#xff0c;如果你想了解一个网络服务&#xff0c;执行的第一个功能肯定是写操作&#xff0c;然后才会执行读操作。比如&#xff0c;你要了解ZooKeeper&#xff0c;那么肯定会在zkClient.sh命令行中执行写操作(比如crea…

Dynamic Extraction of Subdialogues for Dialogue Emotion Recognition

对话情感识别的子对话动态提取 摘要1. 介绍2 相关工作2.1 对话上下文建模2.2 常识知识 3 方法3.1 问题定义3.2 模型概述3.3 特征提取模块3.4 依赖性建模3.5 交互式子对话提取模块3.6 重要性增强的多头自注意力模块3.7 子对话框主题提取模块3.8. 分类模块 四、实验4.1 数据集4.1…

JAVA基础之jsp标准标签

jsp动作标签实现实例化一个实体类 <jsp:useBean id"标识符" class"java类名" scope"作用范围"> 传统的java方式实例化一个实体类 Users user new Users(); <%%> id: 对象名 * class:类 创建对象时,完全限定名(包名…

vue3使用el-autocomplete请求远程数据

服务器端 RestController RequestMapping("/teacher") public class TeacherController {Resourceprivate TeacherService teacherService;GetMapping({"/v1/getTop10TeacherByName/","/v1/getTop10TeacherByName/{name}"})public ResultBean&l…

巡检机器人有哪些功能和作用?

在科技如此发达的时代&#xff0c;巡检机器人犹如一位不知疲倦的守护者&#xff0c;悄然走进了我们的生活。它们具备着令人惊叹的功能和作用&#xff0c;成为了保障安全、提高效率的重要力量。那么&#xff0c;巡检机器人功能和作用&#xff1f;下面我们来说说旗晟机器人的几款…

爬虫:爬取豆瓣电影

文章目录 前言一、pandas是什么&#xff1f;二、使用步骤 1.引入库2.读入数据总结 前言 上篇我们将到如何利用xpath的规则&#xff0c;那么这一次&#xff0c;我们将通过案例来告诉读者如何使用Xpath来定位到我们需要的数据&#xff0c;就算你不懂H5代码是怎么个嵌套或者十分复…

Leetcode—387. 字符串中的第一个唯一字符【简单】

2024每日刷题&#xff08;127&#xff09; Leetcode—387. 字符串中的第一个唯一字符 实现代码 class Solution { public:int firstUniqChar(string s) {int count[26] {0};for(char c: s) {count[c - a];}for(int i 0; i < s.length(); i) {if(count[s[i] - a] 1) {re…

LSTM神经网络 vs Transformer在量化中的应用

LSTM,全称Long Short-Term Memory,是一种特殊的递归神经网络。它通过巧妙的"门"结构,可以有效地捕捉时间序列数据中的长期依赖关系。这一特点,使得LSTM在处理股价这种具有时间序列特性的数据时,展现出了非凡的潜力。 这种特殊的递归神经网络 与一般的前馈神经网络不…