cv1.4 访问通道数据
2016-04-13 11:26
375 查看
作者 群号 C语言交流中心 240137450 微信
15013593099
计算总灰度值
#include <iostream> #include <cv.h> #include <cxcore.h> #include <highgui.h> using namespace std; void main() { IplImage* src_img=cvLoadImage("c:\\img\\1.bmp"); //导入图片 IplImage* backImage; backImage = cvCreateImage( cvGetSize(src_img), src_img->depth, 1 ); cvCvtColor(src_img, backImage, CV_BGR2GRAY );//3通道->1通道 cvShowImage("gray",backImage); size_t total=0; //图像总灰度值 size_t intensity = 0; //每个像素灰度值 size_t height=backImage->height; size_t width =backImage->width; for (size_t rows=0;rows<height;rows++) { uchar* ptr = (uchar*)backImage->imageData+rows*width; for (size_t cols=0;cols<width;cols++) { intensity=(int)ptr[cols]; // cout<<intensity<<"\t"; if(intensity) total+=intensity; } } cout<<"图像总的灰度值为:"<<total<<endl; cvWaitKey(); }
访问通道数据
如果我们要遍历图像中的元素,只需:[cpp]
view plain
copy
IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);
uchar* tmp;
for(int i=0;i<img->height;i++)
for(int j=0;j<img->width;j++)
*tmp=((uchar *)(img->imageData + i*img->widthStep))[j];
这种直接访问的方法速度快,但容易出错,我们可以通过定义指针来访问。即:
[cpp]
view plain
copy
IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);
ucha* data=(uchar *)img->imageData;
int step = img->widthStep/sizeof(uchar);
uchar* tmp;
for(int i=0;i<img->height;i++)
for(int j=0;j<img->width;j++)
*tmp=data[i*step+j];
中(Bi,Bj)(Gi,Gj)(Ri,Rj)表示图像(i,j)处BGR分量的值。使用指针的遍历方法如下:
[cpp]
view plain
copy
IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);
IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,3);
uchar* data=(uchar *)img->imageData;
int step = img->widthStep/sizeof(uchar);
int channels = img->nChannels;
uchar *b,*g,*r;
for(int i=0;i<img->height;i++)
for(int j=0;j<img->width;j++){
*b=data[i*step+j*chanels+0];
*g=data[i*step+j*chanels+1];
*r=data[i*step+j*chanels+2];
}
因此,单通道图像像素访问方式如下:
[cpp]
view plain
copy
IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);
double tmp;
for(int i=0;i<img->height;i++)
for(int j=0;j<img->width;j++)
tmp=cvGet2D(img,i,j).val[0];
多通道字节型/浮点型图像:
[cpp]
view plain
copy
IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_32F,3);
double tmpb,tmpg,bmpr;
for(int i=0;i<img->height;i++)
for(int j=0;j<img->width;j++){
tmpb=cvGet2D(img,i,j).val[0];
tmpg=cvGet2D(img,i,j).val[1];
tmpr=cvGet2D(img,i,j).val[2];
}
如果是修改元素的值,可用cvSet*D(一般是cvSet2D)函数:
[cpp]
view plain
copy
void cvSet1D( CvArr* arr, int idx0, CvScalar value );
void cvSet2D( CvArr* arr, int idx0, int idx1, CvScalar value );
void cvSet3D( CvArr* arr, int idx0, int idx1, int idx2, CvScalar value );
void cvSetND( CvArr* arr, int* idx, CvScalar value );
直方图
直方图统计
//main文件 #include <opencv2/opencv.hpp> using namespace cv; using namespace std; #include "Histogram.h" int main(){ cv::Mat image = cv::imread("f:\\Img\\Lena.jpg"); Histogram h; cv::namedWindow("Red"); cv::namedWindow("Blue"); cv::namedWindow("Green"); cv::namedWindow("Original"); cv::imshow("Original",image); cv::imshow("Red",h.getHistogramImage(image,2)); cv::imshow("Green",h.getHistogramImage(image,1)); cv::imshow("Blue",h.getHistogramImage(image)); cv::waitKey(0); return 0; } Histogram cpp文件 #include "Histogram.h" Histogram::Histogram() { histSize[0] = 256; hrangee[0] = 0.0; hrangee[1] = 255.0; ranges[0] = hrangee; channels[0] = 0; } cv::Mat Histogram::getHistogram(const cv::Mat& image){ cv::MatND hist; cv::calcHist(&image, 1, channels, cv::Mat(), hist, 1, histSize, ranges); return hist; } cv::Mat Histogram::getHistogramImage(const cv::Mat& image, int channel){ std::vector<cv::Mat> planes; cv::split(image,planes); cv::Scalar color; if(planes.size() == 1){ channel = 0; color = cv::Scalar(0,0,0); }else{ color = cv::Scalar(channel==0?255:0, channel==1?255:0, channel==2?255:0); } cv::MatND hist = getHistogram(planes[channel]); double maxVal = 0; double minVal = 0; cv::minMaxLoc(hist, &minVal, &maxVal, 0, 0); cv::Mat histImg(histSize[0], histSize[0], CV_8UC3, cv::Scalar(255,255,255)); int hpt = static_cast<int>(0.9*histSize[0]); for(int h=0; h<histSize[0]-1; h++){ float binVal = hist.at<float>(h); float binVal2 = hist.at<float>(h+1); int intensity = static_cast<int>(binVal*hpt/maxVal); int intensity2 = static_cast<int>(binVal2*hpt/maxVal); cv::line(histImg, cv::Point(h,histSize[0]-intensity), cv::Point(h,histSize[0]-intensity2), color); } return histImg; } Histogram头文件 #ifndef HISTOGRAM_H_ #define HISTOGRAM_H_ #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc/imgproc.hpp> #include <iostream> #include <vector> class Histogram { private: int histSize[1]; float hrangee[2]; const float* ranges[1]; int channels[1]; protected: cv::Mat getHistogram(const cv::Mat&); public: Histogram(); cv::Mat getHistogramImage(const cv::Mat&, int channel = 0); }; #endif /* HISTOGRAM_H_ */
直方图均衡化
#include <opencv2/opencv.hpp> using namespace cv; using namespace std; int main(){ Mat mat = imread("f:\\img\\changhong.jpg"); Mat mergeImg;//合并后的图像 //用来存储各通道图片的向量 vector<Mat> splitBGR(mat.channels()); //分割通道,存储到splitBGR中 split(mat,splitBGR); //对各个通道分别进行直方图均衡化 for(int i=0; i<mat.channels(); i++) equalizeHist(splitBGR[i],splitBGR[i]); //合并通道 merge(splitBGR,mergeImg); imshow("src",mat); imshow("hist",mergeImg); cv::waitKey(0); return 0; }
数硬币
#include <stdio.h> #include<iostream> #include <cv.h> #include <cxcore.h> #include <highgui.h> using namespace std; #include "stdafx.h" #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc/imgproc.hpp> #include <iostream> #include <opencv2/legacy/legacy.hpp> using namespace cv; using namespace std; /// 全局变量的声明与初始化 const int alpha_slider_max = 255; int alpha_slider; double alpha; double beta; /// 声明存储图像的变量 IplImage* backImage; IplImage* backtempImage; IplImage* src_img; /** * @function on_trackbar * @定义响应滑动条的回调函数 */ void on_trackbar( int, void* ) { // cvCvtColor( backImage, src_img ,CV_BGR2GRAY ); cvThreshold(backImage,backtempImage,alpha_slider,255,CV_THRESH_BINARY); cvShowImage( "Linear Blend", backtempImage ); } void main() { src_img=cvLoadImage("c:\\img\\4.png"); //导入图片 backImage = cvCreateImage( cvGetSize(src_img), src_img->depth, 1 ); backtempImage=cvCreateImage( cvGetSize(src_img), src_img->depth, 1 ); cvCvtColor(src_img, backImage, CV_BGR2GRAY );//3通道->1通道 cvShowImage("gray",backImage); size_t total=0; //图像总灰度值 size_t intensity = 0; //每个像素灰度值 size_t height=backImage->height; size_t width =backImage->width; for (size_t rows=0;rows<height;rows++) { uchar* ptr = (uchar*)backImage->imageData+rows*width; for (size_t cols=0;cols<width;cols++) { intensity=(int)ptr[cols]; // cout<<intensity<<"\t"; if(intensity) total+=intensity; } } int avr=total/(height*width); for (size_t rows=0;rows<height;rows++) { uchar* ptr = (uchar*)backImage->imageData+rows*width; for (size_t cols=0;cols<width;cols++) { if(ptr[cols]>avr)ptr[cols]-=avr; else ptr[cols]=avr-ptr[cols]; } } cvShowImage("sub",backImage); /// 初始化为零 alpha_slider = 0; /// 创建窗体 namedWindow("Linear Blend", 1); /// 在创建的窗体中创建一个滑动条控件 char TrackbarName[50]; sprintf( TrackbarName, "Alpha x %d", alpha_slider_max ); createTrackbar( TrackbarName, "Linear Blend", &alpha_slider, alpha_slider_max, on_trackbar ); IplImage* cvThresholdImage; cvThresholdImage = cvCreateImage( cvGetSize(src_img), src_img->depth, 1 ); cvThreshold(backImage,cvThresholdImage,25,255,CV_THRESH_BINARY); cvShowImage("cvThresholdImage",cvThresholdImage); cout<<"图像总的灰度值为:"<<total<<endl; cvWaitKey(); }
tracker bar
#include <stdio.h> #include<iostream> #include <cv.h> #include <cxcore.h> #include <highgui.h> using namespace std; #include "stdafx.h" #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc/imgproc.hpp> #include <iostream> #include <opencv2/legacy/legacy.hpp> using namespace cv; using namespace std; /// 全局变量的声明与初始化 const int alpha_slider_max = 255; int alpha_slider; double alpha; double beta; /// 声明存储图像的变量 Mat src1; Mat src2; Mat dst; /** * @function on_trackbar * @定义响应滑动条的回调函数 */ void on_trackbar( int, void* ) { cvtColor( src1, src2 ,CV_BGR2GRAY ); threshold(src2,dst,alpha_slider,255,CV_THRESH_BINARY); imshow( "Linear Blend", dst ); } int main( int argc, char** argv ) { /// 加载图像 (两图像的大小与类型要相同) src1 = imread("c:\\img\\3.jpg"); if( !src1.data ) { printf("Error loading src1 \n"); return -1; } /// 初始化为零 alpha_slider = 0; /// 创建窗体 namedWindow("Linear Blend", 1); /// 在创建的窗体中创建一个滑动条控件 char TrackbarName[50]; sprintf( TrackbarName, "Alpha x %d", alpha_slider_max ); createTrackbar( TrackbarName, "Linear Blend", &alpha_slider, alpha_slider_max, on_trackbar ); /// 结果在回调函数中显示 // on_trackbar( alpha_slider, 0 ); /// 按任意键退出 waitKey(0); return 0; }
sift
#include <cv.h> #include <highgui.h> #include <math.h> #include <iostream> using namespace std; #include <cv.h> #include <cxcore.h> #include <highgui.h> #include "cv.h" #include "highgui.h" #include <stdio.h> #include "stdafx.h" #include <opencv2/opencv.hpp> #include <opencv2/features2d/features2d.hpp> #include<opencv2/nonfree/nonfree.hpp> #include<opencv2/legacy/legacy.hpp> #include<vector> using namespace std; using namespace cv; int _tmain(int argc, _TCHAR* argv[]) { const char* imagename = "f:\\img\\ball.jpg"; //从文件中读入图像 Mat img = imread(imagename); Mat img2=imread("f:\\img\\ball2.jpg"); //如果读入图像失败 if(img.empty()) { fprintf(stderr, "Can not load image %s\n", imagename); return -1; } if(img2.empty()) { fprintf(stderr, "Can not load image %s\n", imagename); return -1; } //显示图像 imshow("image before", img); imshow("image2 before",img2); //sift特征检测 SiftFeatureDetector siftdtc; vector<KeyPoint>kp1,kp2; siftdtc.detect(img,kp1); Mat outimg1; drawKeypoints(img,kp1,outimg1); imshow("image1 keypoints",outimg1); KeyPoint kp; vector<KeyPoint>::iterator itvc; for(itvc=kp1.begin();itvc!=kp1.end();itvc++) { cout<<"angle:"<<itvc->angle<<"\t"<<itvc->class_id<<"\t"<<itvc->octave<<"\t"<<itvc->pt<<"\t"<<itvc->response<<endl; } siftdtc.detect(img2,kp2); Mat outimg2; drawKeypoints(img2,kp2,outimg2); imshow("image2 keypoints",outimg2); SiftDescriptorExtractor extractor; Mat descriptor1,descriptor2; BruteForceMatcher<L2<float>> matcher; vector<DMatch> matches; Mat img_matches; extractor.compute(img,kp1,descriptor1); extractor.compute(img2,kp2,descriptor2); imshow("desc",descriptor1); cout<<endl<<descriptor1<<endl; matcher.match(descriptor1,descriptor2,matches); drawMatches(img,kp1,img2,kp2,matches,img_matches); imshow("matches",img_matches); //此函数等待按键,按键盘任意键就返回 waitKey(); return 0; }
OPENCV下SIFT特征点提取与匹配的大致流程如下:
读取图片-》特征点检测(位置,角度,层)-》特征点描述的提取(16*8维的特征向量)-》匹配-》显示
其中,特征点提取主要有两个步骤,见上行黄子部分。下面做具体分析。
1、使用opencv内置的库读取两幅图片
2、生成一个SiftFeatureDetector的对象,这个对象顾名思义就是SIFT特征的探测器,用它来探测衣服图片中SIFT点的特征,存到一个KeyPoint类型的vector中。这里有必要说keypoint的数据结构,涉及内容较多,具体分析查看opencv中keypoint数据结构分析,里面讲的自认为讲的还算详细(表打我……)。简而言之最重要的一点在于:
keypoint只是保存了opencv的sift库检测到的特征点的一些基本信息,但sift所提取出来的特征向量其实不是在这个里面,特征向量通过SiftDescriptorExtractor 提取,结果放在一个Mat的数据结构中。这个数据结构才真正保存了该特征点所对应的特征向量。具体见后文对SiftDescriptorExtractor 所生成的对象的详解。
就因为这点没有理解明白耽误了一上午的时间。哭死!
3、对图像所有KEYPOINT提取其特征向量:
得到keypoint只是达到了关键点的位置,方向等信息,并无该特征点的特征向量,要想提取得到特征向量就还要进行SiftDescriptorExtractor 的工作,建立了SiftDescriptorExtractor 对象后,通过该对象,对之前SIFT产生的特征点进行遍历,找到该特征点所对应的128维特征向量。具体方法参见opencv中SiftDescriptorExtractor所做的SIFT特征向量提取工作简单分析。通过这一步后,所有keypoint关键点的特征向量被保存到了一个MAT的数据结构中,作为特征。
4、对两幅图的特征向量进行匹配,得到匹配值。
两幅图片的特征向量被提取出来后,我们就可以使用BruteForceMatcher对象对两幅图片的descriptor进行匹配,得到匹配的结果到matches中,这其中具体的匹配方法暂没细看,过段时间补上。
至此,SIFT从特征点的探测到最后的匹配都已经完成,虽然匹配部分不甚了解,只扫对于如何使用OPENCV进行sift特征的提取有了一定的理解。接下来可以开始进行下一步的工作了。
sift用途
#include <cv.h> #include <highgui.h> #include <math.h> #include <iostream> using namespace std; #include <cv.h> #include <cxcore.h> #include <highgui.h> #include "cv.h" #include "highgui.h" #include <stdio.h> #include "stdafx.h" #include <opencv2/opencv.hpp> #include <opencv2/features2d/features2d.hpp> #include<opencv2/nonfree/nonfree.hpp> #include<opencv2/legacy/legacy.hpp> #include<vector> using namespace std; using namespace cv; #include <opencv2/opencv.hpp> #include <opencv2/nonfree/nonfree.hpp> #include <opencv2/nonfree/features2d.hpp> using namespace std; using namespace cv; void main() { Mat image = imread("f:\\img\\2.bmp"); Mat descriptors; vector<KeyPoint> keypoints; initModule_nonfree(); Ptr<Feature2D> sift = Algorithm::create<Feature2D>("Feature2D.SIFT"); (*sift)(image, noArray(), keypoints, descriptors); Ptr<FeatureDetector> Fast_detect = Algorithm::create<FeatureDetector>("Feat ure2D.FAST"); //Ptr<DescriptorExtractor> Fast_extract = Algorithm::create<Feature2D>("Featur e2D.FAST"); //Fast_detect->detect(image,keypoints); //Fast_extract->compute(img,kepoints,descriptors); drawKeypoints(image, keypoints, image, Scalar(255,0,0),4); imshow("test", image); waitKey(); }
相关文章推荐
- 希尔排序
- linux 文件权限——文件系统的文件及文件夹的权限管理标准详尽
- 二叉树基础算法总结
- markdown使用
- 产品设计:58同城与赶集网APP改版建议
- IOS开发多线程篇—GCD介绍
- ionic cordova 控制iOS状态栏的显示,隐藏,颜色
- IOS开发多线程篇—GCD介绍
- Nuwa热修复在项目中应用
- Spring+Struts+Hibernate框架详解
- Web应用——驾培管理系统之框架搭建
- xgboost note
- 轻松把玩HttpClient之封装HttpClient工具类(五),携带Cookie的请求
- Qt学习: Model/View实现表格和统计图
- 【bc】计算器
- 【bash】编程之常用命令
- 计算文件夹内视频总长度工具
- [译]How to Write a Git Commit Message
- RecyclerView左右滑动及拖动排序
- keepalived实现高可用集群方案