我的编译环境是vs2012,opencv-2.4.9,要在附加依赖项中添加:opencv_core249d.lib opencv_highgui249d.lib opencv_imgproc249d.lib。也可以在代码里面添加以下内容:
- #pragma comment(lib,"opencv_core249d.lib")
- #pragma comment(lib,"opencv_highgui249d.lib")
- #pragma comment(lib,"opencv_imgproc249d.lib")
2.下面这个联系是帮助掌握矩阵类型。创造一个三通道二维矩阵,字节类型,大小为100X100,并设置所有数值为0。
a.在矩阵中使用void cvCircle(CvArr* img,CvPoint center,int radius,CvScalar color,int thickness=1,int line_type=8,int shift=0)画一个圆。
b.使用第2章所学的方法来显示这幅图像。
CvMat* mat=cvCreateMat(100,100,CV_8UC3);
cvSetZero(mat);
cvCircle(mat,cvPoint(mat->width/2,mat->height/2),mat->width/3,CV_RGB(255,0,0) );
cvNamedWindow(winName,CV_WINDOW_AUTOSIZE);
cvShowImage(winName,mat);
cvWaitKey(0);
3.创建一个有用三个通道的二维字节类型矩阵,大小为100X100,并将所有值赋为0。通过函数cvPtr2D将指针指向中间的通道(“”绿色“)。以(20,5)与(40,20)为顶点间画一个绿色的长方形。
CvMat* mat=cvCreateMat(100,100,CV_8UC3);
cvZero(mat);
unsigned char* pMat=cvPtr2D(mat,0,0);
for (int i=0;i<mat->cols;i++)
{
for (int j=0;j<mat->rows;j++)
{
pMat=cvPtr2D(mat,i,j);
if (isThePointInRectangel(i,j)== true)
{
//使pMat指向绿色通道
*(pMat+1)=255;
}
}
}
cvNamedWindow(winName,CV_WINDOW_AUTOSIZE);
cvShowImage(winName,mat);
cvWaitKey(0);
cvReleaseMat(&mat);
cvDestroyWindow(winName);
<span style="white-space:pre"> </span>IplImage* img=cvCreateImage(cvSize(100,100),8,3);
cvZero(img);
for (int y=5;y<=20;y++)
{
unsigned char* pImg=(unsigned char*)(img->imageData+y*img->widthStep);
for (int x=20;x<=40;x++)
{
//3个通道
*(pImg+3 * x +1)=255;
//或
//pImg[3 * x +1]=255;
}
}
cvNamedWindow(winName);
cvShowImage(winName,img);
cvWaitKey(0);
cvReleaseImage(&img);
cvDestroyWindow(winName);
5.练习使用感兴趣区域(ROI)。创建一个210X210的单通道图像并将其归0。在图像中使用ROI和cvSet()建立一个增长如金字塔状的数组。也就是:外部边界为0,下一个内部边界应该为20,再下一个内部边界为40依此类推,直到最后内部值为200;所有的边界应该为10个像素的宽度。最后显示这个图形。
<span style="white-space:pre"> </span>int x=0;
int y=0;
int width=210;
int height=210;
int color=0;
int edge=10;
int raiseColor=20;
int nBreakValue=200;
IplImage* img=cvCreateImage(cvSize(width,height),IPL_DEPTH_8U,1);
cvZero(img);
while (true)
{
cvSetImageROI(img,cvRect(x,y,width,height) );
cvSet(img,cvScalar(color) );
x+=edge;
y+=edge;
width-=2*edge;
height-=2*edge;
color+=raiseColor;
cvResetImageROI(img);
if (color>nBreakValue)
{
break;
}
}
cvNamedWindow(winName,CV_WINDOW_AUTOSIZE);
cvShowImage(winName,img);
cvWaitKey(0);
cvReleaseImage(&img);
cvDestroyWindow(winName);
6.为一个图像创建多个图像头。读取一个大小至少为100X100的图像。另创建两个图像头并设置它们的origion,depth,nChannels和widthStep属性同之前读取的图像一样。在新的图像头中,设置宽度为20,高度为30。最后,将imageData指针分别指向像素(5,10)和(50,60)像素位置。传递这两个新的图像头给cvNot()。最后显示最初读取的图像,在那个大图像中应该有两个矩形,矩形内的值是原始值的求反值。
<span style="white-space:pre"> </span>int width=20;
int height=30;
IplImage* img=cvLoadImage("2.jpeg");
int depth=img->depth;
int channel=img->nChannels;
int origin=img->origin;
int widthStep=img->widthStep;
IplImage* img1=cvCreateImageHeader(cvSize(width,height),depth,channel);
IplImage* img2=cvCreateImageHeader(cvSize(width,height),depth,channel);
img1->origin=origin;
img2->origin=origin;
img1->widthStep=widthStep;
img2->widthStep=widthStep;
img1->imageData=img->imageData+10* img->widthStep+5*img->nChannels;
img2->imageData=img->imageData+60* img->widthStep+50*img->nChannels;
cvNot(img1,img1);
cvNot(img2,img2);
cvNamedWindow(winName);
cvShowImage(winName,img);
cvWaitKey(0);
cvReleaseImage(&img1);
cvReleaseImage(&img2);
cvReleaseImage(&img);
cvDestroyWindow(winName);
7.使用cvCmp()创建一个掩码。加载一个真实的图像。使用cvSplit()将图像分割成红,绿,蓝三个当通道图像。
a.找到并显示绿图。
b.克隆这个绿图两次(分别命名为clone1和clone2)。
c求出这个绿色平面的最大值和最小值。
d.将clone1的所有元素赋值为thresh=(unsigned char)((最大值-最小值)/2.0)。
e.将clone2所有元素赋值为0,然后调用函数cvCmp(green_image,clone1,clone2,CV_CMP_GE)。现在clone2将是一个标识绿图中值超过thresh的掩码图像。
f.最后,使用cvSubS(green_image,thresh/2,green_image,clone2)函数并显示结果。
<span style="white-space:pre"> </span>const char* winImgPre="img_pre";
const char* winImgG="img_Green";
const char* winImgGA="img_Green_after";
IplImage* img=cvLoadImage("2.jpeg");
cvNamedWindow(winImgPre);
cvShowImage(winImgPre,img);
IplImage* imgR=cvCreateImage(cvSize(img->width,img->height),img->depth,1);
IplImage* imgG=cvCreateImage(cvSize(img->width,img->height),img->depth,1);
IplImage* imgB=cvCreateImage(cvSize(img->width,img->height),img->depth,1);
cvSplit(img,imgG,imgB,imgR,NULL);
cvNamedWindow(winImgG);
cvShowImage(winImgG,imgG);
IplImage* clone1=cvCloneImage(imgG);
IplImage* clone2=cvCloneImage(imgG);
double maxNum,minNum;
cvMinMaxLoc(imgG,&minNum,&maxNum);
cout<<"MinNum in imgG:"<<minNum<<endl;
cout<<"MaxNum in imgG:"<<maxNum<<endl;
double scalar=(maxNum-minNum)/2;
cvSet(clone1,cvScalar(scalar) );
cvSetZero(clone2);
cvCmp(imgG,clone1,clone2,CV_CMP_GE);
cvSubS(imgG,cvScalar(scalar/2),imgG,clone2);
cvNamedWindow(winImgGA);
cvShowImage(winImgGA,imgG);
cvWaitKey(0);
cvReleaseImage(&img);
cvReleaseImage(&imgG);
cvDestroyWindow(winName);
cvDestroyWindow(winImgG);
cvDestroyWindow(winImgGA);
cvReleaseImage(&clone2);
8.创建一个结构,结构中包含一个整数,一个CvPoint和一个CvRect;称结构为"my_struct"。
a.写两个函数:void write_my_struct(CvFileStorage* fs,const char* name,my_struct* ms)和void read_my_struct(CvFileStorage* fs,CvFileNode* ms_node,my_struct* ms)。用它们读、写my_struct。
b.创建一个元素为my_struct结构体且长度为10的数组,并将数组写入磁盘和从磁盘读入内存。
#include "highgui.h"
#include <iostream>
using namespace std;
typedef struct
{
int i;
CvPoint pt;
CvRect rect;
}my_struct;
void write_my_struct(CvFileStorage* fs,const char* name,my_struct* ms)
{
assert(fs !=0);
cvWriteInt(fs,"i",ms->i);
cvStartWriteStruct(fs,"pt",CV_NODE_SEQ);
cvWriteInt(fs,0,ms->pt.x);
cvWriteInt(fs,0,ms->pt.y);
cvEndWriteStruct(fs);
cvStartWriteStruct(fs,"rect",CV_NODE_SEQ);
cvWriteInt(fs,0,ms->rect.x);
cvWriteInt(fs,0,ms->rect.y);
cvWriteInt(fs,0,ms->rect.width);
cvWriteInt(fs,0,ms->rect.height);
cvEndWriteStruct(fs);
}
void read_my_struct(CvFileStorage* fs,CvFileNode* ms_node,my_struct* ms)
{
assert(fs !=0);
ms->i=cvReadIntByName(fs,0,"i",0);
CvSeq* s=cvGetFileNodeByName(fs,0,"pt")->data.seq;
ms->pt.x=cvReadInt((CvFileNode*)cvGetSeqElem(s,0) );
ms->pt.y=cvReadInt((CvFileNode*)cvGetSeqElem(s,1) );
CvSeq* s1=cvGetFileNodeByName(fs,0,"rect")->data.seq;
ms->rect.x=cvReadInt((CvFileNode*)cvGetSeqElem(s1,0) );
ms->rect.y=cvReadInt((CvFileNode*)cvGetSeqElem(s1,1) );
ms->rect.width=cvReadInt((CvFileNode*)cvGetSeqElem(s1,2) );
ms->rect.height=cvReadInt((CvFileNode*)cvGetSeqElem(s1,3) );
//输出读取的结果
cout<<"my_struct:"<<endl;
cout<<"i:"<<ms->i<<endl;
cout<<"pt:("<<ms->pt.x<<","<<ms->pt.y<<")"<<endl;
cout<<"rect:("<<ms->rect.x<<","<<ms->rect.y<<","<<ms->rect.width<<","<<ms->rect.height<<endl;
}
<span style="white-space:pre"> </span>CvFileStorage* fs=cvOpenFileStorage("cfg.xml",0,CV_STORAGE_WRITE);
my_struct ms;
ms.i=100;
ms.pt.x=10;
ms.pt.y=20;
ms.rect.x=30;
ms.rect.y=40;
ms.rect.width=50;
ms.rect.height=60;
write_my_struct(fs,NULL,&ms);
cvReleaseFileStorage(&fs);
//往xml文件中读数据
CvFileStorage* fs1=cvOpenFileStorage("cfg.xml",0,CV_STORAGE_READ);
my_struct ms1;
read_my_struct(fs1,NULL,&ms1);
cvReleaseFileStorage(&fs1);
cin.get();