您的位置:首页 > 其它

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();

}



                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: