opencv+图像特征

首先明确两个问题,①为什么要引进图像特征?②什么是图像特征? 简而言之,引入图像特征的目的就是让计算机能够识别图像,比如抓取到图片A中有长鼻子那么判断图片A为大象,抓取到图片B有长耳朵,那么可以说图片B为兔子。那么什么是图像特征?通俗来讲,就是图像本身能够同其他图片进行区分的一些特征,这些特征在进行尺寸变化,或者非复杂仿射变换时依然存在的一些特征。图像特征能够解决的问题包括有识别,定位,追踪,三维重建等。下面上干货

#include <iostream>
#include <opencv2/opencv.hpp>
#include "highgui/highgui.hpp"    
#include "opencv2/nonfree/nonfree.hpp"    
#include "opencv2/legacy/legacy.hpp"  
using namespace std;
using namespace cv;
Mat src, dst;
vector<vector<Point>> contours;
void detect_default()
{
//利用图像的表征识别出图像的缺陷

//利用绝对阈值寻找图像中的黑点
src=imread("default.bmp", 0);
threshold(src, dst, 10, 255, THRESH_BINARY_INV);
Mat draw_src = src.clone();
findContours(dst, contours, RETR_EXTERNAL, CHAIN_APPROX_NONE);

//这里并未对轮廓的周长以及面积进行判断,特殊情况需自行判断特征类型
for (int i = 0; i < contours.size(); i++)
{
Rect m_rect = boundingRect(contours[i]);
rectangle(draw_src, Rect(m_rect.x - 5, m_rect.y - 5, m_rect.width + 10, m_rect.height + 10),200,1);
}
imshow("黑点缺陷", draw_src);


//利用相对阈值寻找图像中的凹点
src = imread("default.bmp", 0);
dst = src.clone();
blur(dst, dst, Size(3, 3), Point(-1, -1));
adaptiveThreshold(dst, dst, 255, ADAPTIVE_THRESH_GAUSSIAN_C, THRESH_BINARY_INV, 15, 20);
contours.clear();
draw_src = src.clone();
findContours(dst, contours, RETR_EXTERNAL, CHAIN_APPROX_NONE);
for (int i = 0; i < contours.size(); i++)
{
Rect m_rect = boundingRect(contours[i]);
rectangle(draw_src, Rect(m_rect.x - 8, m_rect.y - 8, m_rect.width + 16, m_rect.height + 16), 200, 1);
}
imshow("凹缺陷", draw_src);
waitKey(0);
}
void model_match()
{
//图像的相关性,既指图像自身像素间的相关性,比如寻找连通区域。也可指不同图像之间的相关性,比如模板匹配
//下面用模板匹配,来寻找图中的匹配物
src = imread("dota2.jpg", 0);
Mat draw_src=imread("dota2.jpg");
imshow("原图", src);
Mat model = imread("model.jpg",0);
imshow("模型", model);
Mat res;
matchTemplate(src, model, res, 0);
Point min_point,max_point;
double match_value;
minMaxLoc(res, &match_value, NULL, &min_point, &max_point);
rectangle(draw_src, Rect(min_point.x, min_point.y, model.cols, model.rows), Scalar(0,0,255), 1);
}
void pca_calc()
{
//谈到pca的时候,我们做个假设,假设图像是由10块积木搭成的,其中第一块的一块占据了这个图像的80%
//第二块占据了图像的10%,第三块占据了图像的5%,依次类推,然后,我们把这张图拆成10块积木,拿出前两块拼好
//然后我说,这两块是可以代表这幅图的,显然这是个伪命题,但从一定程度来说,这两块的确能代表整幅图。这就是PCA的
//思想,我们用svd对一张图进行分解,分解出来的就是图像的特征,也可以说是奇异值,然后对这些奇异值进行重组,
//这就能起到降维的作用

Mat img = imread("timg.jpg", IMREAD_GRAYSCALE);
imshow("原图", img);
img.convertTo(img, CV_32FC1);//转换为float类型  
string tile = "压缩比率";
Mat U, W, VT;
SVD svd;
//这里进行奇异值分解
svd.compute(img, W, U, VT);

//将矩阵进行压缩  
//原始数据进行压缩之后是 m*m m*n n*n  
//由于特征值在前几行中占有的比率是比较大的,所以,仅仅选择前几行(r)作为好的特征值  
//那么分解的结果就变为 m*r r*r r*n 这样的形式  
double radio = 1;//压缩比率  
int rows = radio*img.rows;
Mat WROI = Mat::zeros(rows, rows, CV_32FC1);//W矩阵的大小  
//填充举着WROI,这里的i就是控制奇异值的输出量,奇异值从大到小排列,这里的i去0到rows,就是完美复原,取0到30就处于原图近似
for (int i = 0; i < 30; ++i)
{
WROI.at<float>(i, i) = W.at<float>(i);
}
Mat UROI = U.colRange(0, rows);//主要注意的是,colrange中不包含End  
Mat VTROI = VT.rowRange(0, rows);
Mat Result = UROI*WROI*VTROI;
Result.convertTo(Result, CV_8UC1);
namedWindow(tile);
imshow(tile, Result);
waitKey(0);
}
void feature_match()
{
//大脑在接收视觉的时候,他会关注图像中有这突变的点,不管是像素值上的突变,还是轮廓上的突变,
//opencv也有类似的算法,他能自动帮你找出这些突变的点,surf是其中一个,下面采用的是surf的一个变种算法SIFT
//sift比起surf的一个好处是他能够解决遮挡以及背景混乱的问题


Mat image01 = imread("view1.png", 1);
Mat image02 = imread("view2.png", 1);
imshow("p2", image01);
imshow("p1", image02);


//灰度图转换  
Mat image1, image2;
cvtColor(image01, image1, CV_RGB2GRAY);
cvtColor(image02, image2, CV_RGB2GRAY);




//提取特征点    
SurfFeatureDetector surfDetector(2000);  // 海塞矩阵阈值,在这里调整精度,值越大点越少,越精准 
vector<KeyPoint> keyPoint1, keyPoint2;
surfDetector.detect(image1, keyPoint1);
surfDetector.detect(image2, keyPoint2);


//特征点描述,为下边的特征点匹配做准备    
SurfDescriptorExtractor SurfDescriptor;
Mat imageDesc1, imageDesc2;
SurfDescriptor.compute(image1, keyPoint1, imageDesc1);
SurfDescriptor.compute(image2, keyPoint2, imageDesc2);


FlannBasedMatcher matcher;
vector<vector<DMatch> > matchePoints;
vector<DMatch> GoodMatchePoints;


vector<Mat> train_desc(1, imageDesc1);
matcher.add(train_desc);
matcher.train();


matcher.knnMatch(imageDesc2, matchePoints, 2);
cout << "total match points: " << matchePoints.size() << endl;


// Lowe's algorithm,获取优秀匹配点
for (int i = 0; i < matchePoints.size(); i++)
{
if (matchePoints[i][0].distance < 0.6 * matchePoints[i][1].distance)
{
GoodMatchePoints.push_back(matchePoints[i][0]);
}
}


Mat first_match;
drawMatches(image02, keyPoint2, image01, keyPoint1, GoodMatchePoints, first_match);
imshow("first_match ", first_match);
waitKey();




}
int main()
{
//基于像素变化的缺陷查找
detect_default();
//基于特征向量的svd以及pca
pca_calc();
//基于特征点的特征点匹配
feature_match();
//基于统计特征:轮廓的周长&面积,像素的均值&偏差,全局但不局限于全局上的直方图,基于卷积的描绘子等
model_match();

namedWindow("main", WINDOW_AUTOSIZE);


return 0;






}

下面这是detect_deafult()的效果


这是pca_calc()的效果图



下面是feature_match()的效果图


下面是model_match()的效果图



猜你喜欢

转载自blog.csdn.net/qq_37333087/article/details/80733131
今日推荐