【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; // 提示正在重新计算PCA


    double var = pos / 100.0; // 将滑动条的整型位置值转换为[0,1]之间的百分比表示的保留方差


    struct params *p = (struct params *)ptr; // 从回调函数的指针参数中提取出params结构体


    // 使用新的保留方差重新计算PCA
    p->pca = PCA(p->data, cv::Mat(), PCA::DATA_AS_ROW, var); 


    // 将原始数据的第一行(第一幅图像)投影到PCA空间,并获取其点representation
    Mat 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;
    
    // 创建trackbar
    int 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 rowMatrix
    Mat data = formatImagesForPCA(images);


    // perform PCA
    PCA 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 image
    Mat 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 shape
    reconstruction = 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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

数据结构之单链表相关刷题

找往期文章包括但不限于本期文章中不懂的知识点&#xff1a; 个人主页&#xff1a;我要学编程(ಥ_ಥ)-CSDN博客 所属专栏&#xff1a;数据结构 数据结构之单链表的相关知识点及应用-CSDN博客 下面题目基于上面这篇文章&#xff1a; 下面有任何不懂的地方欢迎在评论区留言或…

OpenAI CEO山姆·奥特曼推广新AI企业服务,直面微软竞争|TodayAI

近期&#xff0c;OpenAI的首席执行官山姆奥特曼在全球多地接待了来自《财富》500强公司的数百名高管&#xff0c;展示了公司最新的人工智能服务。在旧金山、纽约和伦敦的会议上&#xff0c;奥特曼及其团队向企业界领袖展示了OpenAI的企业级产品&#xff0c;并进行了与微软产品的…

ansible的常见用法

目录 ##编辑hosts文件 ##copy模块##复制过去 ##fetch模块##拉取 ##shell模块 ##好用 ##command模块## ##file模块### ##cron模块### ##crontab 计划任务 ##下载好时间插件 ##script模块 ##yum模块## ##yum下载源配置文件 /etc/yum.repos.d/CentOS-Base.repo ##ser…

【opencv】示例-minarea.cpp 如何寻找一组随机生成的点的最小外接矩形、三角形和圆...

// 包含OpenCV库的高GUI模块和图像处理模块的头文件 #include "opencv2/highgui.hpp" #include "opencv2/imgproc.hpp"// 包含标准输入输出流的头文件 #include <iostream>// 使用命名空间cv和std&#xff0c;这样我们就可以直接使用OpenCV和标准库的…

Vitis HLS 学习笔记--ap_int.h / ap_fixed.h(1)

目录 目录 1. 概述 2. 简要规则 3. 浮点运算的复杂性 2.1 对阶 3.2 尾数运算 3.3 规格化和舍入 3.4 特殊值的处理 4. 示例&#xff08;ap_fixed.h&#xff09; 5. 量化模式&#xff08;ap_fixed.h&#xff09; 5.1 AP_SAT* 模式会增加资源用量 1. 概述 ap_int.h 和…

【网站项目】摄影竞赛小程序

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

【opencv】示例-opencv_version.cpp 输出OpenCV的版本和构建配置的示例

#include <opencv2/core/utility.hpp> // 引入OpenCV核心工具库 #include <iostream> // 引入标准输入输出流库// 定义一个包含命令行参数的字符串 static const std::string keys "{ b build | | print complete build info }" // 定义参数b&#xff…

2024年大唐杯官网模拟题

单选(出题角度很奇怪&#xff0c;不用太纠结&#xff09; 5G NR系统中&#xff0c;基于SSB的NR同频测量在measconfig里最多可以配置&#xff08; &#xff09;个SMTC窗口。 A、3 B、4 C、1 D、2 答案&#xff1a;D 2个 5G 中从BBU到AAU需要保证&#xff08; &#xff09;Gbps…

千视电子携NDI 6前沿技术,亮相北京CCBN展呈现轻量化媒体解决方案

千视携NDI 6技术闪耀2024 CCBN展会&#xff0c;呈现轻量化媒体解决方案 2024年4月24日至26日&#xff0c;北京首钢会展中心将举办第三十届中国国际广播电视网络技术展览会&#xff08;CCBN2024&#xff09;。这是中国广播电视行业的一项重要盛会&#xff0c;将有国内外超600家…

Linux硬件管理

文章目录 Linux硬件管理1.查看磁盘空间 df -h2.查看文件的磁盘占用空间 du -ah3.查看系统内存占用情况 htop Linux硬件管理 1.查看磁盘空间 df -h 语法 df [选项][参数]选项 -a或–all&#xff1a;包含全部的文件系统&#xff1b; –block-size<区块大小>&#xff1a;…

Unity打包出来的apk安装时提示应用程式与手机不兼容,无法安装应用程式

1、遇到的问题 * 2、解决办法 这是因为你在Unity中导出来的apk手机安装包是32位的&#xff0c;才导致上述问题发生&#xff0c;要解决这个办法&#xff0c;需要在Unity中导出64位的手机安装包。 32位跟64位的区别&#xff0c;以及如何区分打出来的手机安装包是否是32位或者是…

Centos服务器安装MySQL

Centos服务器安装MySQL 利用闲置服务器安装MySQL&#xff0c;用于项目练手 Linux版本&#xff1a;Centos7.9 MySQL版本&#xff1a;8.0.36 一、下载MySQL 从Oracle官网下载最新版本的MySQL wget https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-8.0.36-1.el7.x86_64.rp…

【OTA】STM32新能源汽车OTA技术ymodem协议PC串口升级过程

【OTA】STM32新能源汽车OTA技术ymodem协议PC串口升级过程 文章目录 前言一、实验工具1.串口USB线——烧录APP2生成的BIN文件2.STLINK——烧录BOOT代码和APP1代码3.烧录工具——将BIN文件烧录到单片机中4.FLYMCU——清除芯片FLASH 二、硬件绘制1.原理图2.PCB 三、软件配置1.BOOT…

zookeeper和kafka消息队列

zookeeper zookeeper介绍 Zookeeper是一个开源的分布式的&#xff0c;为分布式框架提供协调服务的Apache项目 zookeeper特点 zookeeper是由一个领导者(leader)&#xff0c;多个跟随者(follower)组成的集群 Zookeepe集群中只要有半数以上节点存活&#xff0c;Zookeeper集群…

express服务器 authorization 前端获取不到的问题

服务器生成token 设置在响应头&#xff0c;但是前端获取不到 const token JWT.generate({ id: new Date().getTime(), userName }, 10s) res.header(Authorization, token) axios.interceptors.response.use((response) > {console.log(response);if (response.data?.co…

关于Zookeeper+Kafka集群

文章目录 一、Zookeeper1、Zookeeper定义2、Zookeeper工作机制3、Zookeeper特点4、Zookeeper数据结构5、Zookeeper应用场景5.1 统一命名服务5.2 统一配置管理5.3 统一集群管理5.4 服务器动态上下线5.5 软负载均衡 6、Zookeeper 选举机制6.1 第一次启动选举机制6.2 非第一次启动…

ccframe系统的链路追踪,用户ID追踪的实现

需求 之前ccframe cloud V1用的是springcloud微服务&#xff0c;只需要在header将jwttoken一直传下去就没事&#xff0c;最近弄V2转dubbo发现用户id没有自动保存进数据库表。于是开始研究dubbo如何追踪&#xff0c;顺便把链路追踪ID的问题给一并解决掉。 理论 MDC MDC&…

Sonar下启动发生错误,elasticsearch启动错误

Download | SonarQube | Sonar (sonarsource.com) 1.首先我的sonar版本为 10.4.1 &#xff0c;java版本为17 2.sonar启动需要数据库,我先安装了mysql, 但是目前sonar从7.9开始不支持mysql&#xff0c;且java版本要最少11,推荐使用java17 3.安装postsql,创建sonar数据库 4.启…

海洋信息管理系统:守护蓝色星球,促进海洋经济新发展

海洋&#xff0c;覆盖地球表面超过七成的广阔水域&#xff0c;是生命之源&#xff0c;也是经济发展的重要空间。然而&#xff0c;随着人类活动的增加&#xff0c;海洋生态环境面临严峻挑战&#xff0c;海洋资源的可持续利用成为全球关注的焦点。在这样的背景下&#xff0c;构建…

爱奇艺APP Android低端机性能优化

01 背景介绍 在智能手机市场上&#xff0c;高端机型经常备受瞩目&#xff0c;但低端机型亦占据了不可忽视的份额。众多厂商为满足低端市场的需求&#xff0c;不断推出低配系列手机。另外过去几年的中高端机型&#xff0c;随着系统硬件的快速迭代&#xff0c;现已经被归类为低端…