使用openCV与C++求图片特征值及特征向量并进行图片处理
利用openCV求图片特征值及特征向量
1、运用openCV与c++所涉及的头文件
#include<iostream>
#include<cstring>
#include<highgui.h>
#include<opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc.hpp>
using namespace std;
using namespace cv;//工程所需头文件
- 1
- 2
- 3
- 4
- 5
- 6
- 7
2、以灰度形式导入图片
Mat image;
image =imread("C:\\Users\\taekookie\\source\\repos\\图片处理\\图片处理\\任务.jpg",0);//通过绝对路径导入图片
imshow("原图", image);//展示原图
waitKey(0);
destroyAllWindows();
- 1
- 2
- 3
- 4
最开始读入图片时选择的是相对路径imread(“任务.jpg"),在代码调试时报错,故而改为了绝对路径。而imshow()函数使用时,需保持独立单一窗口,否则会出现图片显示未响应现象,所以代码中加入了waitKey();与 destroyAllWindows()。
3、将图片像素值矩阵转变为可操作的数据类型
Mat src;
image.convertTo(src, CV_32FC1);
- 1
4、通过open CV中的eigen()计算特征值与特征向量
cv::Mat eValuesMat;//特征值
cv::Mat eVectorsMat;//特征向量
eigen(src, eValuesMat, eVectorsMat);//通过openCV中eigen函数得到特征值与特征向量
- 1
- 2
5.1、保留最大的50个特征值对图片进行处理
a、对特征值进行排序
for (int i = 0; i < eValuesMat.rows; i++)//对特征值进行由大到小的排序
{
for (int j = 1; j < eValuesMat.rows - i; j++)
{
if (eValuesMat.at<float>(i,0) < eValuesMat.at<float>(i + j,0))
{
p = eValuesMat.at<float>(i+j, 0);
eValuesMat.at<float>(i, 0) = eValuesMat.at<float>(i + j, 0);
eValuesMat.at<float>(i + j, 0) = p;
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
b、选取最大的50个特征值
int m=50;
Mat Max(eValuesMat.rows, eValuesMat.rows, eValuesMat.type(), Scalar(0));
for (int i = 0; i < m; i++)
{
Max.ptr<float>(i)[i] = eValuesMat.ptr<float>(i)[0];//最大的m个特征值组成的对角阵
}
- 1
- 2
- 3
- 4
- 5
- 6
c、求解特征向量的逆阵
eVectorsMat = eVectorsMat.t();//eigen函数所得特征向量以行形式存储,故而进行转置后再参与运算
Mat inv;
invert(eVectorsMat, inv);//对特征向量矩阵求逆
- 1
- 2
由于特征向量是以行形式承载,故先进行转置
d、计算新的矩阵,并以RGB图片形式保存
new_src1 = eVectorsMat * Max * inv;
new_src1.convertTo(new_src1, CV_8UC1);//转换新矩阵数据类型
cvtColor(new_src1, new_src1, CV_GRAY2RGB);//改变图片类型
imwrite("Max.jpg", new_src1);
- 1
- 2
- 3
e、由于openCV中eigen()函数只处理矩阵的上三角部分,所以还需要将src进行转置,处理下三角部分,并使两部分拼接在一起才能真正实现图片完整的处理
Mat img=imread("C:\\Users\\taekookie\\source\\repos\\test\\test\\Max.jpg", 0);
Mat timg = imread("C:\\Users\\taekookie\\source\\repos\\test\\test\\Max1.jpg", 0);
Mat s, ts;
img.convertTo(s, CV_32FC1);
timg.convertTo(s, CV_32FC1);
for (int i = 0; i < 512; i++)//实现上三角部分与下三角部分图片的拼接
{
s.at<float>(i, j) = ts.at<float>(i, j);
}
imwrite("finalR.jpg", s);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
5.2、随机选取50个特征值对图片进行处理
a、通过srand()函数随机选取50个特征值
unsigned n=50;
srand(n);//通过随机函数取相应数量特征值
int i = 0, j = 0;
while (i = rand() % (eValuesMat.rows) + 1)
{
if (j == (eValuesMat.rows - 50))break;
eValuesMat.at<float>(i, 0) = 0;
j++;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
b、eigen()函数形成的特征值不是对角阵形式,故进行特征值对角化
Mat vals(eValuesMat.rows, eValuesMat.rows, eValuesMat.type(), Scalar(0));//由于eigen函数得到的特征值非对角阵形式,故而将其转换成对角阵形式
float* vals_data = eValuesMat.ptr<float>(0);//通过Mat类自带指针与自定义指针类进行赋值
for (i = 0; i < eValuesMat.rows; i++)
{
vals.ptr<float>(i)[i] = vals_data[i];
}
- 1
- 2
- 3
- 4
- 5
c、计算新矩阵并保存(代码与5.1(d)类似)
d、进行上三角部分与下三角部分的拼接(代码与5.1(e)类似)
6、效果呈现
原图:
选取最大的50个特征值:
a、上三角部分
b、下三角部分
c、拼接后:
随机选取50个特征值:
a、上三角:
b、下三角
c、拼接后
赞 (0)