Opencv第三章练习题答案

23 篇文章 0 订阅

我的编译环境是vs2012,opencv-2.4.9,要在附加依赖项中添加:opencv_core249d.lib opencv_highgui249d.lib opencv_imgproc249d.lib。也可以在代码里面添加以下内容:

  1. #pragma comment(lib,"opencv_core249d.lib")  
  2. #pragma comment(lib,"opencv_highgui249d.lib")  
  3. #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);



4.创建一个大小为100X100的三通道RGB图像。将它的元素全部置0。使用指针算法以(20,5)与(40,20)为顶点绘制一个绿色平面。

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


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值