当前位置: 首页 > news >正文

【opencv】示例-pca.cpp PCA图像重建演示

9d8824bc74e020f2f6f57fd81556519b.png

1e34152a1ccbb16d3ebe76f61c4db5f9.png

// 加载必要的头文件
#include <iostream> // 用于标准输入输出流
#include <fstream>  // 用于文件的输入输出
#include <sstream>  // 用于字符串的输入输出流操作#include <opencv2/core.hpp>          // OpenCV核心功能的头文件
#include "opencv2/imgcodecs.hpp"     // OpenCV图像编解码功能的头文件
#include <opencv2/highgui.hpp>       // OpenCV的高级GUI(图形用户界面)// 使用标准命名空间和OpenCV命名空间,避免重复声明
using namespace cv;
using namespace std;///
// 函数声明部分// read_imgList函数用于从文本文件中读取图像路径并加载这些图像
static void read_imgList(const string& filename, vector<Mat>& images) {std::ifstream file(filename.c_str(), ifstream::in); // 打开文件if (!file) {string error_message = "No valid input file was given, please check the given filename."; // 错误消息CV_Error(Error::StsBadArg, error_message); // 如果文件打开失败,给出错误信息并退出程序}string line; // 存储读取的每行文字while (getline(file, line)) {images.push_back(imread(line, IMREAD_GRAYSCALE)); // 将每行读取到的图像路径用于加载图像,并转换为灰度图像}
}// formatImagesForPCA函数用于将图像数据格式化为一个适合PCA处理的矩阵
static  Mat formatImagesForPCA(const vector<Mat> &data)
{// 创建一个用于PCA处理的矩阵,将所有图像行向量垂直堆叠Mat dst(static_cast<int>(data.size()), data[0].rows*data[0].cols, CV_32F);for(unsigned int i = 0; i < data.size(); i++) // 遍历所有图像{Mat image_row = data[i].clone().reshape(1,1); // 将每张图像转换为行向量Mat row_i = dst.row(i); // 获取目标矩阵的当前行image_row.convertTo(row_i,CV_32F); // 将图像数据转换为浮点型,并填入目标矩阵的相应行}return dst; // 返回格式化后的矩阵
}// toGrayscale函数用于将输入图像转换为灰度图像,并进行归一化处理
static Mat toGrayscale(InputArray _src) {Mat src = _src.getMat(); // 获取输入数据的Mat对象// 检查是否是单通道图像if(src.channels() != 1) {CV_Error(Error::StsBadArg, "Only Matrices with one channel are supported"); // 如果不是,抛出异常}// 创建一个目标Mat对象,并对输入图像进行归一化处理Mat dst;cv::normalize(_src, dst, 0, 255, NORM_MINMAX, CV_8UC1);return dst; // 返回处理后的图像
}// 定义一个结构体用于传递给滑动条回调函数的参数
struct params
{Mat data;    // 存放数据的Mat矩阵int ch;      // 图像的通道数int rows;    // 图像行数PCA pca;     // PCA对象string winName; // 窗口名称
};// onTrackbar滑动条回调函数,用于根据Retained Variance(保留方差)的变化更新PCA结果并显示
static void onTrackbar(int pos, void* ptr)
{cout << "Retained Variance = " << pos << "%   ";cout << "re-calculating PCA..." << std::flush; // 提示正在重新计算PCAdouble var = pos / 100.0; // 将滑动条的整型位置值转换为[0,1]之间的百分比表示的保留方差struct params *p = (struct params *)ptr; // 从回调函数的指针参数中提取出params结构体// 使用新的保留方差重新计算PCAp->pca = PCA(p->data, cv::Mat(), PCA::DATA_AS_ROW, var); // 将原始数据的第一行(第一幅图像)投影到PCA空间,并获取其点representationMat point = p->pca.project(p->data.row(0));// 然后利用该点representation重构图像Mat reconstruction = p->pca.backProject(point);reconstruction = reconstruction.reshape(p->ch, p->rows); // 重构的图像需要重新改变其形状reconstruction = toGrayscale(reconstruction); // 转换为灰度图便于显示// 在窗口中显示重构的图像imshow(p->winName, reconstruction);// 打印PCA使用的主成分数量cout << "done!   # of principal components: " << p->pca.eigenvectors.rows << endl;
}///
// 主程序
int main(int argc, char** argv)
{// 解析命令行参数cv::CommandLineParser parser(argc, argv, "{@input||image list}{help h||show help message}");// 如果存在"help"参数,则打印帮助消息if (parser.has("help")){parser.printMessage();exit(0);}// 获取CSV文件的路径string imgList = parser.get<string>("@input");// 如果未传入图片列表,则打印消息并退出程序if (imgList.empty()){parser.printMessage();exit(1);}// 创建一个向量来存储图像vector<Mat> images;// 读取数据,如果失败则会抛出异常try {read_imgList(imgList, images);} catch (const cv::Exception& e) {cerr << "Error opening file \"" << imgList << "\". Reason: " << e.msg << endl;exit(1);}// 如果图片不足以进行此演示,则退出程序if(images.size() <= 1) {string error_message = "This demo needs at least 2 images to work. Please add more images to your data set!";CV_Error(Error::StsError, error_message);}// 将图像重排并堆叠成一个行矩阵Mat data = formatImagesForPCA(images);// 执行PCA// 这里trackbar初始设置为95%,这也是一个常见的保留方差值PCA pca(data, cv::Mat(), PCA::DATA_AS_ROW, 0.95); // 展示保留方差对第一张图片效果的演示Mat point = pca.project(data.row(0)); // 将图像投影到特征空间,图像变成了一个“点”Mat reconstruction = pca.backProject(point); // 从“点”中重建图像reconstruction = reconstruction.reshape(images[0].channels(), images[0].rows); // 重新将行向量变形为图像形状reconstruction = toGrayscale(reconstruction); // 重新缩放以便于显示// 初始化高层GUI窗口string winName = "Reconstruction | press 'q' to quit";namedWindow(winName, WINDOW_NORMAL);// 创建一个结构体以传递给trackbar处理函数params p;p.data = data;p.ch = images[0].channels();p.rows = images[0].rows;p.pca = pca;p.winName = winName;// 创建trackbarint pos = 95;createTrackbar("Retained Variance (%)", winName, &pos, 100, onTrackbar, (void*)&p);// 显示直到用户按下'q'键imshow(winName, reconstruction);char key = 0;while(key != 'q')key = (char)waitKey();return 0;
}

代码的主要功能是,通过用户输入一个包含图像全路径的文本文件,该文件的每一行都代表一张图片的路径。程序将会使用主成分分析(PCA)技术对这些图像进行处理,并通过OpenCV库完成。这一处理过程可以通过一个trackbar(滑动条)来动态调整保留方差的百分比,从而展现不同保留方差下图像重建的效果。程序界面会持续显示直到用户按下'q'键退出。这个代码示例建议使用AT&T人脸数据库的前15个人脸图片来演示。

deea6de5c56344233ef92d62c4895658.png

// Reshape and stack images into a rowMatrixMat data = formatImagesForPCA(images);// perform PCAPCA pca(data, cv::Mat(), PCA::DATA_AS_ROW, 0.95); // trackbar is initially set here, also this is a common value for retainedVariance// Demonstration of the effect of retainedVariance on the first imageMat point = pca.project(data.row(0)); // project into the eigenspace, thus the image becomes a "point"Mat reconstruction = pca.backProject(point); // re-create the image from the "point"reconstruction = reconstruction.reshape(images[0].channels(), images[0].rows); // reshape from a row vector into image shapereconstruction = toGrayscale(reconstruction); // re-scale for displaying purposes

969da80f26830e803bf8409ab8367148.png

56ebb477b87a3d2e5e4e3feb3a611741.png

imageslist.txt

https://www.kaggle.com/datasets/kasikrit/att-database-of-faces?resource=download  数据下载地址

200e34188f5960c69e20dff0b117cf6f.png

468fd6b3f463a29e18332000e54e5225.png

相关文章:

【opencv】示例-pca.cpp PCA图像重建演示

// 加载必要的头文件 #include <iostream> // 用于标准输入输出流 #include <fstream> // 用于文件的输入输出 #include <sstream> // 用于字符串的输入输出流操作#include <opencv2/core.hpp> // OpenCV核心功能的头文件 #include "o…...

C语言中的编译和链接

系列文章目录 文章目录 ​编辑 系列文章目录 文章目录 前言 一、 翻译环境和运行环境 二、 翻译环境 2.1 编译 2.1.1 预处理 2.1.2 编译 2.1.2.1 词法分析 : 2.1.2.2 语法分析 2.1.2.3 语义分析 2.1.3 汇编 2.2 链接 三、运行环境 前言 在我们平常的写代码时&#xff0c;我们很…...

如何将三方库集成到hap包中——通过IDE集成cmak构建方式的C/C++三方库

简介 cmake构建方式是开源三方库的主流构建方式。DevEco Studio目前以支持cmake的构建方式。本文将通过在IDE上适配cJSON三方库为例讲来解如何在IDE上集成cmake构建方式得三方库。 创建工程 在开发进行三方库适配以及napi接口开发前&#xff0c;我们需要创建一个三方库对应的…...

Towards Street-Level Client-Independent IP Geolocation(2011年)(第二部分)

被引次数:306 Wang Y, Burgener D, Flores M, et al. Towards {Street-Level}{Client-Independent}{IP} Geolocation[C]//8th USENIX Symposium on Networked Systems Design and Implementation (NSDI 11). 2011. 接着Towards Street-Level Client-Independent IP Geolocati…...

软件测试过程和测试生命周期

众所周知&#xff0c;软件生命周期包括&#xff0c;需求阶段、设计阶段、设计构建阶段、测试周期阶段、最后测试、实施阶段、最后运维和维护验收。每个阶段都需要在软件开发的生命周期中从前一阶段交付。需求转化为设计&#xff0c;设计转化为开发和开发成测试&#xff0c;经过…...

python-study-day1

ps&#xff1a;前言 可做毕设&#xff0c;html&#xff0c;web&#xff0c;app&#xff0c;小程序&#xff0c;bug修改&#xff0c;可加急 作者自述 作为一名前端开发工程师&#xff0c;这个大环境不好的情况下&#xff0c;我试过我前端接单子但是没有后端&#xff0c…...

【Apache2】彻底删除 Apache2 服务器

要彻底删除 Apache2 服务器&#xff0c;需要卸载 Apache2 软件包并删除其配置文件和数据文件。在 Ubuntu 上&#xff0c;可以按照以下步骤来完成&#xff1a; 停止 Apache2 服务&#xff1a; sudo systemctl stop apache2卸载 Apache2 软件包&#xff1a; sudo apt-get purge a…...

C#:成绩等级转换

任务描述 本关任务&#xff1a;给出一百分制成绩&#xff0c;要求输出成绩等级‘A’、‘B’、‘C’、‘D’、‘E’。 90分以上为A 80-89分为B 70-79分为C 60-69分为D 60分以下为E&#xff0c;如果输入数据不在0~100范围内&#xff0c;请输出一行&#xff1a;“Score is error!”…...

每日OJ题_01背包③_力扣494. 目标和(dp+滚动数组优化)

目录 力扣494. 目标和 问题解析 解析代码 滚动数组优化代码 力扣494. 目标和 494. 目标和 难度 中等 给你一个非负整数数组 nums 和一个整数 target 。 向数组中的每个整数前添加 或 - &#xff0c;然后串联起所有整数&#xff0c;可以构造一个 表达式 &#xff1a; …...

vue3+element plus图片预览点击按钮直接显示图片的预览形式

1 需求 直接上需求&#xff1a; 我想要直接点击下面这个“预览”按钮&#xff0c;然后呈现出预览图片的形式 ok&#xff0c;需求知道了&#xff0c;下面让我们来看看如何实现吧 ~ 2 实现 template部分 <el-buttontype"primary"size"small"click&qu…...

GAMS104 现代游戏引擎 2

渲染的难点可以分为一下三部分&#xff1a;如何计算入射光线、如何考虑材质以及如何实现全局光照。 渲染的难点之一在于阴影&#xff0c;或者说是光的可见性。如何做出合适的阴影效果远比想象中要难得多&#xff0c;在实践中往往需要通过大量的技巧才能实现符合人认知的阴影效…...

spring boot学习第十七篇:OAuth2概述及使用GitHub登录第三方网站

0. 导言 我们在浏览器上可以访问成百上千个网站&#xff0c;使用每个网站的服务一般都要先注册账号&#xff0c;那么我们为了更好地记忆&#xff0c;一般都会在多个网站使用相同的账号和密码进行注册。那么问题就来了&#xff0c;如果在你注册的网站中有某些个网站的系统设计不…...

基于springboot的电影评论网站系统源码数据库

基于springboot的电影评论网站系统源码数据库 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已逐步成熟。本文介绍了电影评论网站的开发全过程。通过分析电影评论网站管理的不足&#xff0c;创建了一个计算机管理电影评论网站的方案。文…...

javaScript手写专题——实现instanceof/call/apply/bind/new的过程/继承方式

目录 原型链相关 手写instanceof 实现一个_instance方法&#xff0c;判断对象obj是否是target的实例 测试 手写new的过程 实现一个myNew方法&#xff0c;接收一个构造函数以及构造函数的参数&#xff0c;返回构造函数创建的实例对象 测试myNew方法 手写类的继承 ES6&…...

C++11 新特性:tuple 元组

std::tuple是 C11 中引入的一个非常强大的类型&#xff0c;它允许将多个类型不同的值&#xff0c;组合成单一对象。 std::tuple非常适合用于那些需要返回多个值的场景&#xff0c;而且它的灵活性和通用性使得其成为现代 C 编程中不可或缺的一部分。下面&#xff0c;我们将探讨…...

最齐全,最简单的免费SSL证书获取方法——实现HTTPS访问

一&#xff1a;阿里云 优势&#xff1a;大平台&#xff0c;在站长中知名度最高&#xff0c;提供20张免费单域名SSL证书 缺点&#xff1a;数量有限&#xff0c;并且只有单域名证书&#xff0c;通配符以及多域名没有免费版本。并且提供的单域名证书只有三个月的期限。 二&#…...

c语言->贪吃蛇实战技巧结合EasyX简单实现页面管理(简单实现)

✅作者简介&#xff1a;大家好&#xff0c;我是橘橙黄又青&#xff0c;一个想要与大家共同进步的男人&#x1f609;&#x1f609; &#x1f34e;个人主页&#xff1a;再无B&#xff5e;U&#xff5e;G-CSDN博客 1. 游戏背景 贪吃蛇是久负盛名的游戏&#xff0c;它也和俄罗斯⽅…...

C语言-详解内存函数

文章目录 1.memcpy使用和模拟实现1.1 memcpy函数的使用规则1.2 memcpy函数的使用1.2 模拟实现memcpy函数 2.memmove 函数的使用和模拟实现2.1 memmove 函数使用规则2.2 memmove函数的使用2.3 模拟实现memmove函数2.3.1 从后往前移2.3.2 从前往后移 2.4 算法实现2.4.1 从前往后移…...

【核心完整复现】基于目标级联法的微网群多主体分布式优化调度

1 主要内容 之前发布了华电学报的复现程序《基于目标级联法的微网群多主体分布式优化调度》&#xff0c;具体链接为【防骗版】基于目标级联法的微网群多主体分布式优化调度&#xff0c;虽然对模型及结果进行了复现&#xff0c;但是部分模型细节和参数并没有完全实现&#xff0…...

Mac下安装NVM,NVM安装Node(附带NPM)

1、理解NVM、node、NPM 什么是NVM&#xff1f; NVM: Node.js Version Manager&#xff0c;用来管理 node 的版本。 什么是 Node.js? Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境。 Node.js使用了一个事件驱动、非阻塞式I/O的模型&#xff08; Node.js的特性&…...

python-flask-djangol框架的的畜牧站疾病防控与检测系统

目录技术选型与架构设计核心功能模块实现数据可视化与决策支持移动端适配与离线功能测试与部署方案项目技术支持源码获取详细视频演示 &#xff1a;文章底部获取博主联系方式&#xff01;同行可合作技术选型与架构设计 后端采用Python Flask框架&#xff0c;轻量级且灵活性高&…...

Ubuntu服务器中文乱码终极解决方案:从locale配置到阿里云重启避坑指南

Ubuntu服务器中文乱码终极解决方案&#xff1a;从locale配置到阿里云重启避坑指南 当你第一次在Ubuntu服务器上看到中文字符变成一堆问号或方框时&#xff0c;那种困惑和挫败感我深有体会。特别是在云服务器环境下&#xff0c;问题往往比本地环境更复杂——即使按照常规教程操作…...

别再瞎找了!盘点2026年顶流之选的AI论文写作软件

一天写完毕业论文在2026年已不再是天方夜谭。2026年最炸裂的AI论文写作软件来了&#xff0c;实测提速效果惊人&#xff0c;覆盖选题、撰写、查重、排版全流程&#xff0c;让你高效搞定论文不再难。 一、全流程王者&#xff1a;一站式搞定论文全链路&#xff08;一天定稿首选&am…...

手把手教你用Swaks和Gophish绕过SPF,搭建自己的邮件钓鱼测试环境(附避坑指南)

企业级邮件安全测试实战&#xff1a;从SPF绕过到钓鱼环境搭建 邮件安全测试已成为企业安全防护体系中不可或缺的一环。据统计&#xff0c;超过90%的网络攻击始于钓鱼邮件&#xff0c;而其中近40%的成功攻击源于SPF配置不当或完全缺失。本文将系统性地介绍如何构建一个完整的邮件…...

云原生实战:如何用GROUP模型提升容器工作负载预测准确率(附避坑指南)

云原生实战&#xff1a;如何用GROUP模型提升容器工作负载预测准确率&#xff08;附避坑指南&#xff09; 在云原生架构中&#xff0c;容器资源管理一直是DevOps团队面临的重大挑战。传统单容器预测方法往往忽视了微服务间复杂的协同关系&#xff0c;导致预测误差居高不下。本文…...

告别重复代码:BaseMapperPlus在SpringBoot项目中的5个高级用法

BaseMapperPlus实战&#xff1a;SpringBoot项目中提升开发效率的5个高阶技巧 在SpringBoot项目中使用MyBatis-Plus进行数据持久层开发时&#xff0c;BaseMapperPlus作为社区广泛采用的扩展接口&#xff0c;能显著减少模板代码。本文将分享五个实际业务场景中的高阶用法&#xf…...

DevExpress GridControl动态添加行的两种高效实现方式

1. 两种动态添加行的核心方法对比 刚接触DevExpress GridControl时&#xff0c;最让我头疼的就是动态添加行这个基础操作。网上教程要么太零散&#xff0c;要么直接贴代码不解释原理。经过多个项目实战&#xff0c;我总结出最高效的两种实现方式&#xff0c;就像给表格数据&quo…...

LangGraph实战:从零构建并部署一个多功能智能体

1. LangGraph框架概述&#xff1a;新一代智能体开发范式 在人工智能应用开发领域&#xff0c;智能体&#xff08;Agent&#xff09;技术正经历着从简单问答到复杂任务执行的进化。LangGraph作为LangChain生态中的新一代开发框架&#xff0c;彻底改变了传统链式结构的局限性。我…...

STM32智能甲鱼养殖系统设计与实现

基于STM32的智能甲鱼养殖系统设计与实现1. 项目概述1.1 系统背景现代水产养殖行业正面临从传统人工管理向智能化转型的关键时期。甲鱼作为对水质环境敏感的特种水产品&#xff0c;其养殖过程中需要持续监测多项水质参数并保持稳定环境。传统人工监测方式存在响应滞后、精度不足…...

2026 LinkedIn账号安全机制分析与稳定运营实践

随着 LinkedIn 风控机制的不断完善&#xff0c;账号的登录环境、行为模式以及网络条件&#xff0c;都会直接影响账号的稳定性。对于需要长期运营账号的用户来说&#xff0c;理解平台的风控逻辑&#xff0c;比单纯增加操作频率更为重要。本文将从使用场景、常见环境问题、账号行…...