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

news2025/6/9 2:07:41

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

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

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

相关文章

Upload-labs(Pass-17--Pass-21)

Pass-17 二次渲染图片马/条件竞争 二次渲染就是在我们上传的图片后&#xff0c;网站会对图片进行二次处理&#xff0c;比如对图片的尺寸、格式、以及网站对图片进行定义的一些要求等进行处理&#xff0c;并且服务器会对里面的内容进行二次替换更新&#xff0c;在处理完后&…

【深度学习】图像超分辨

案例 7&#xff1a;图像超分辨 相关知识点&#xff1a;生成对抗网络、图像处理&#xff08;PIL&#xff09;和可视化&#xff08;matplotlib&#xff09; 1 任务目标 1.1 任务和数据简介 ​ 本次案例将使用生成对抗网络来实现 4 倍图像超分辨任务&#xff0c;输入一张低分辨…

搭建基于Hexo的个人博客,以及git相关命令

全文写完之后的总结 测试命令 hexo clean hexo g hexo s 上传到服务器命令 hexo clean hexo g hexo d 上传到服务器&#xff08;如果上一个命令用不了&#xff09;&#xff0c;也要先hexo clean,hexo g git init git add . git commit -m "first commit" git p…

.NET i18n 多语言支持与国际化

环境 WIN10 VS2022 .NET8 1.&#x1f44b;创建项目 2.&#x1f440;创建Resources Controllers HomeController.en.resx HomeController.fr.resx HomeController.zh.resx 3.&#x1f331;Program.cs添加国际化支持 // 添加国际化支持 builder.Services.AddLocalization(…

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

【GD32】MQ-3酒精检测传感器

2.31 MQ-3酒精检测传感器 MQ-3气体传感器所使用的气敏材料是在清洁空气中电导率较低的二氧化锡(Sn0)。当传感器所处环境中存在酒精蒸气时&#xff0c;传感器的电导率随空气中酒精蒸气浓度的增加而增大。使用简单的电路即可将电导率的变化转换为与该气体浓度相对应的输出信号。…

设计模式代码实战-装饰者模式

1、问题描述 小明喜欢品尝不同口味的咖啡&#xff0c;他发现每种咖啡都可以加入不同的调料&#xff0c;比如牛奶、糖和巧克力。他决定使用装饰者模式制作自己喜欢的咖啡。 请设计一个简单的咖啡制作系统&#xff0c;使用装饰者模式为咖啡添加不同的调料。系统支持两种咖啡类型…

【Vue + keep-alive】路由缓存

一. 需求 列表页&#xff0c;n 条数据项可打开 n 个标签页&#xff0c;同时1条数据项的查看和编辑共用一个标签页。如下所示&#xff1a; 参考 // 主页面 // 解决因 路由缓存&#xff0c;导致 编辑后跳转到该页面 不能实时更新数据 onActivated(() > {getList() })二. 实现…

ISP图像处理pipeline简介1

ISP 是什么&#xff1f; ISP (Image Signal Processor)&#xff0c;图像信号处理器&#xff0c;是用于摄影和视频处理的一种专用芯片。它是用来干什么的呢&#xff1f;简单说就是用来将图像传感器&#xff08;CCD, CMOS&#xff09;信号转化成可视的信号的功能&#xff0c;这里…

基于Docker构建CI/CD工具链(八)用nginx收集测试报告

当前&#xff0c;我们已经介绍了如何使用 Apifox 和 JMeter 进行测试&#xff0c;尽管控制台已经输出了测试结果&#xff0c;但在实际工作中&#xff0c;我们通常需要更详细的测试报告。 测试报告在测试过程中已经生成&#xff0c;只需将其托管起来以便查阅。如果你有现成的 C…

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

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

【Sql Server】锁表如何解锁,模拟会话事务方式锁定一个表然后进行解锁

大家好&#xff0c;我是全栈小5&#xff0c;欢迎来到《小5讲堂》。 这是《Sql Server》系列文章&#xff0c;每篇文章将以博主理解的角度展开讲解。 温馨提示&#xff1a;博主能力有限&#xff0c;理解水平有限&#xff0c;若有不对之处望指正&#xff01; 目录 前言创建表模拟…

11 Php学习:函数

PHP 内建函数Array 函数 PHP Array 函数是 PHP 核心的组成部分。无需安装即可使用这些函数。 创建 PHP 函数 当您需要在 PHP 中封装一段可重复使用的代码块时&#xff0c;可以使用函数。下面详细解释如何创建 PHP 函数并举例说明。 创建 PHP 函数的语法 PHP 函数的基…

ChatGPT深度科研应用、数据分析及机器学习、AI绘图与高效论文撰写

2022年11月30日&#xff0c;可能将成为一个改变人类历史的日子——美国人工智能开发机构OpenAI推出了聊天机器人ChatGPT3.5&#xff0c;将人工智能的发展推向了一个新的高度。2023年4月&#xff0c;更强版本的ChatGPT4.0上线&#xff0c;文本、语音、图像等多模态交互方式使其在…

anaconda创建了虚拟python环境,且安装了pytorch,但是pycharm中import torch运行时报错

报错如下&#xff1a; C:\Users\tashi\.conda\envs\test1\python.exe D:\project\python\transformer\main.py C:\Users\tashi\.conda\envs\test1\lib\site-packages\numpy\__init__.py:127: UserWarning: mkl-service package failed to import, therefore Intel(R) MKL init…

常用接口测试工具/免费api

一 接口编辑文档 常用的接口文档编写apipost 二 免费接口测试 api 1. thecat 含有&#xff1a; The Cat API - Cat as a Service The Cat API 2. public-apis 进入页面往下拉 三 常用接口测试工具 postman 四 常用接口性能测试工具 Jmeter&#xff0c;loadrunner

Java 基于微信小程序的校园失物招领小程序,附源码

博主介绍&#xff1a;✌程序员徐师兄、8年大厂程序员经历。全网粉丝15w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…

错题记录-华为海思

华为 海思数字芯片 参考 &#xff1a;FPGA开发/数字IC笔试系列(5) 华为海思IC笔试解析 FPGA开发/数字IC笔试系列(6) 华为海思IC笔试解析 SystemVerilog Function与Task的区别 $readmemh与$readmemb这两个系统任务是用来从指定文件中读取数据到寄存器数组或者RAM、ROM中。除了…

【opencv】示例-peopledetect.cpp HOG(方向梯度直方图)描述子和SVM(支持向量机)进行行人检测...

// 包含OpenCV项目所需的objdetect模块头文件 #include <opencv2/objdetect.hpp> // 包含OpenCV项目所需的highgui模块头文件&#xff0c;用于图像的显示和简单操作 #include <opencv2/highgui.hpp> // 包含OpenCV项目所需的imgproc模块头文件&#xff0c;用于图像…

Cesium.js--》探秘Cesium背后的3D模型魔力—加载纽约模型

今天简单实现一个Cesium.js的小Demo&#xff0c;加强自己对Cesium知识的掌握与学习&#xff0c;先简单对这个开源库进行一个简单的介绍吧&#xff01; Cesium 是一个开源的地理空间可视化引擎&#xff0c;用于创建基于 Web 的三维地球应用程序。它允许开发人员在网页上呈现高度…