//<学习OPENCV>第3章
//数据结构基本操作
#include<cv.h>
#include<iostream>
#include<opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include <cxcore.h>
#include<assert.h>
float sum( CvMat* mat );
void saturate_sv( IplImage* img );
int main(int argc,char** argv)
{
//----------------------------------------------------------------------
/**创建已知数据的OpenCV矩阵**/
float vals[] = { 0.866025, -0.500000, 0.500000, 0.866025};
//分配矩阵空间:行/列/类型
//cvCreateMat = cvCreateMatHeader + cvCreateData + ...
//cvCreateMatHeader:创建cvMat结构,不为数据分配内存
//cvCreateData:只为数据的内存分配
CvMat* mat = cvCreateMat(5, 5, CV_32FC1); //初始化为0,float,单通道
//CV_MAT_ELEM宏存取矩阵元素,只对单通道矩阵有效
float mat_3_2 = CV_MAT_ELEM( *mat, float, 3, 2 );
printf("matrix created and accessed [3,2]=%f\n",mat_3_2);
float mat_3_1 = 7.7;
//CV_MAT_ELEM_PTR返回指向元素的指针
*((float*)CV_MAT_ELEM_PTR(*mat,3,1)) = mat_3_1;
//cvmSet,cvmGet用于处理浮点型单通道矩阵
//通常情况下,set与get效率很低,一般定义自己的指针计算并且在矩阵中利用自己的方法
cvmSet( mat, 2, 2, 0.5000 );
cvSetReal2D( mat, 3, 3, 0.3300 );//2者等同
printf("mat[3,1]=%f, [2,2]=%f, [3,3]=%f\n",CV_MAT_ELEM(*mat,float,3,1),CV_MAT_ELEM(*mat,float,2,2),CV_MAT_ELEM(*mat,float,3,3 ));
cvWaitKey(0);
//----------------------------------------------------------------------
/**矩阵元素求和**/
CvMat *mat1 = cvCreateMat(5,5,CV_32FC1);
float mat1_3_2 = 7.7;
*((float*)CV_MAT_ELEM_PTR(*mat1,3,2)) = mat1_3_2;
cvmSet(mat1,4,4,0.5000);
cvSetReal2D(mat1,3,3,0.5000);
float s = sum(mat1);
printf("the sum of mat1 is:%f\n",s);
cvWaitKey();
//----------------------------------------------------------------------
/**访问图像数据**/
//3通道图像,设置饱和度和高度,色度不变
IplImage* img = cvLoadImage("D:\\My_Proj\\OPENCV\\dog.jpg");
cvNamedWindow("origin",CV_WINDOW_AUTOSIZE);
cvShowImage("origin",img);
cvNamedWindow("saturate_sv",CV_WINDOW_AUTOSIZE);
saturate_sv(img);
cvShowImage("saturate_sv",img);
cvSaveImage("D:\\My_Proj\\OPENCV\\saturate_sv.jpg",img);
cvWaitKey(0);
cvReleaseImage(&img);
cvDestroyWindow("origin");
cvDestroyWindow("saturate_sv");
//----------------------------------------------------------------------
/**设置图像ROI**/
//ROI与WidthStep允许对图像的一小部分进行运算,提高执行速率
IplImage* src;
cvNamedWindow("image_pre", CV_WINDOW_AUTOSIZE);
cvNamedWindow("image_post", CV_WINDOW_AUTOSIZE);
if((src=cvLoadImage("D:\\My_Proj\\OPENCV\\dog.jpg")) != 0)
{
//将字符串转换为整形,参数分别为ROI左上角坐标,长度和高度
int x = 0;//atoi(argv[2]);
int y = 0;//atoi(argv[3]);
int width = 300;//atoi(argv[4]);
int height = 100;//atoi(argv[5]);
int add = 255;//atoi(argv[6]); //
cvShowImage("image_pre", src);
cvSetImageROI(src, cvRect(x,y,width,height));//设置ROI,后面操作只对ROI区域
//cvAdd:两个数组元素分别相加;cvAddS:数组元素分别与一个标量相加
//cvScalar:4个double类型元素的数据,常用于初始化通道,存放三通道图像中像素:cvScalar(255,255,255)
cvAddS(src,cvScalar(add),src);
cvResetImageROI(src);//取消ROI
cvShowImage( "image_post",src);
cvWaitKey(0);
}
cvReleaseImage( &src );
cvDestroyWindow("image_pre");
cvDestroyWindow("image_post");
//----------------------------------------------------------------------
/**利用WidthStep设置ROI**/
//ROI set和reset只能串行处理ROI
//当需要对图像中多个ROI同时处理时,则用WidthStep
IplImage* interest_img;//初始图像
CvRect interest_rect;//设置2个ROI区域
CvRect interest_rect1;
if(((interest_img=cvLoadImage("D:\\My_Proj\\OPENCV\\dog.jpg")) != 0 ))
{
interest_rect.x = 0;
interest_rect.y = 0;
interest_rect.width = 200;
interest_rect.height = 200;
int add = 100;
interest_rect1.x = 200;
interest_rect1.y = 200;
interest_rect1.width = 100;
interest_rect1.height = 100;
int add1 = 200;
//设置子图像区域
//创建IplImage图像头,制定图像的尺寸,深度和通道数,不包括数据区域
IplImage *sub_img = cvCreateImageHeader(
cvSize(interest_rect.width, interest_rect.height),
interest_img->depth,interest_img->nChannels);
IplImage *sub_img1 = cvCreateImageHeader(
cvSize(interest_rect1.width,interest_rect1.height),
interest_img->depth,interest_img->nChannels);
//设置图像显示属性,origin=0表示左上角为原点,=1为左下角
sub_img->origin = interest_img->origin;
//widthStep:存储一行像素所需字节数,补足4的倍数。
sub_img->widthStep = interest_img->widthStep;
sub_img->imageData = interest_img->imageData + //起始数据域
interest_rect.y * interest_img->widthStep +
interest_rect.x * interest_img->nChannels;
sub_img1->origin = interest_img->origin;
//widthStep:存储一行像素所需字节数,补足4的倍数。
sub_img1->widthStep = interest_img->widthStep;
sub_img1->imageData = interest_img->imageData + //起始数据域
interest_rect1.y * interest_img->widthStep +
interest_rect1.x * interest_img->nChannels;
//对ROI区域进行操作,结果反映在原图像上
cvAddS(sub_img,cvScalar(add),sub_img );
cvAddS(sub_img1,cvScalar(add1),sub_img1 );
cvNamedWindow( "WidthStep", CV_WINDOW_AUTOSIZE );
cvShowImage( "WidthStep", interest_img );
cvReleaseImageHeader(&sub_img);
cvReleaseImageHeader(&sub_img1);
cvDestroyWindow("WidthStep");
cvWaitKey();
}
//----------------------------------------------------------------------
/**2个数据加权相加**/
//cvAddWeighted:src1*alpha+src2*beta+gamma
IplImage *src1, *src2;
if(((src1=cvLoadImage("D:\\My_Proj\\OPENCV\\dog.jpg")) != 0)&&((src2=cvLoadImage("D:\\My_Proj\\OPENCV\\saturate_sv.jpg"))!=0))
{
int x = 200;
int y = 200;
int width = 100;
int height = 100;
double alpha = 0.3;
double beta = 0.5;//(double)atof(argv[8]);
cvSetImageROI(src1, cvRect(x,y,width,height));
cvSetImageROI(src2, cvRect(0,0,width,height));
//cvAddWeighted:src1*alpha+src2*beta+0
//2个源图像、一个目的图像
cvAddWeighted(src1,alpha,src2,beta,0.0,src1);
cvResetImageROI(src1);
cvNamedWindow( "Alpha_blend", 1 );
cvShowImage( "Alpha_blend", src1 );
cvWaitKey();
cvReleaseImage(&src1);
cvReleaseImage(&src2);
cvDestroyWindow("Alpha_blend");
}
else
printf("Couldn't load one or both of %s, %s\n",argv[1],argv[2]);
//----------------------------------------------------------------------
/**写入xml:以xml的格式保存数据**/
CvMat *the_matrix_data = cvCreateMat(5,5,CV_32FC1);
float the_matrix_data_3_2 = 7.7;
*((float*)CV_MAT_ELEM_PTR( *the_matrix_data, 3,2) ) = the_matrix_data_3_2;
cvmSet(the_matrix_data,4,4,0.5000);
cvSetReal2D(the_matrix_data,3,3,0.5000);
CvMat A = cvMat(5,5,CV_32F,the_matrix_data);
printf("Saving my_matrix.xml\n");
cvSave( "D:\\My_Proj\\OPENCV\\my_matrix.xml", &A );
// to load it then in some other program use …
printf("Loading my_matrix.xml\n");
CvMat* A1 = (CvMat*)cvLoad("D:\\My_Proj\\OPENCV\\my_matrix.xml");
cvWaitKey(0);
//----------------------------------------------------------------------
/**写配置文件**/
CvMat *cmatrix = cvCreateMat(5,5,CV_32FC1);
float cmatrix_3_2 = 7.7;
*((float*)CV_MAT_ELEM_PTR( *cmatrix, 3,2) ) = cmatrix_3_2;
cvmSet(cmatrix,4,4,0.5000);
cvSetReal2D(cmatrix,3,3,0.5000);
printf("writing cfg.xml\n");
CvFileStorage* fs = cvOpenFileStorage("D:\\My_Proj\\OPENCV\\cfg.xml",0,CV_STORAGE_WRITE);
cvWriteInt(fs, "frame_count", 10 );//写入整形数据
cvStartWriteStruct(fs,"frame_size",CV_NODE_SEQ);//写入数据结构
cvWriteInt(fs,0,320 );
cvWriteInt(fs,0,200 );
cvEndWriteStruct(fs);
cvWrite( fs,"color_cvt_matrix",cmatrix);
cvReleaseFileStorage(&fs);
}
//求CvMat数组元素和
//计算指向矩阵的指针,注意矩阵元素data是联合体。
//引用这个指针解时,需要指明结构体中的正确的元素一边得到正确的指针类型
float sum( CvMat* mat )
{
float s = 0.0f;
for( int row=0; row<mat->height; row++ )
{
//data union中fl指针(指向float数据),step是以1字节来计算的(每行数据位宽step字节),实际步长为mat->step/4(浮点数的长度为4字节)
float* ptr = mat->data.fl + row*mat->step/4;
for( int col=0; col<mat->width; col++ )
s += *ptr++;
}
return( s );
};
//快速访问图像数据,设置每个点的饱和度和高度
//imageData:指向第一行图像数据的指针
//imageData是cvMat与IplImage重要区别,imageData指针是字节类型uchar*,cvmat不一定。
void saturate_sv(IplImage* img)
{
for(int y=0; y<img->height; y++)
{
uchar* ptr = (uchar*)(img->imageData + y*(img->widthStep));
for(int x=0;x<(img->width);x++) //img->width:每行像素个数
{
ptr[3*x+1] = 128; //输入为3通道RGB图像、设置饱和度和高度值
ptr[3*x+2] = 128;
}
}
}
效果图: