《学习opencv》第三章课后习题详解

第一题:

 

3_1:
// chapter_3.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "stdio.h"
#include "cxcore.h" //处理数据结构
#include "cv.h"
#include "types_c.h"


int _tmain(int argc, _TCHAR* argv[])
{
	printf("a***选取一个负的浮点数,取他的绝对值,四舍五入后,取它的极值***\n");
	double fudian = -123.4532;
	printf("\t默认选取的负数为:%f\n", fudian);
	double fudian1 = fabs(fudian);
	printf("\t其绝对值为:%f\n", fudian1);
	int fudian3 = cvRound(fudian1);
	printf("\t四舍五入之后,极值为:%d\n", fudian3);
	printf("b***产生一些随机数***\n");
	CvRNG rng = cvRNG(cvGetTickCount());
	printf("\t");
	for (int i = 0; i < 10; i++)
	{
		printf("*%d", cvRandInt(&rng) % 256);
	}
	printf("\n");
	printf("c***Cvpoint2D32f类型到CvPoint类型的转换***\n");
	CvPoint2D32f cpf = cvPoint2D32f(89.2345, 78.6745);
	printf("\t该cvpoint2d32f数为%f,%f\n", cpf.x, cpf.y);
	CvPoint cpf1 = cvPointFrom32f(cpf);
	printf("\t转换后的cvpoint数为%d,%d\n", cpf1.x, cpf1.y);
	printf("c***Cvpoint类型到CvPoint2D32f类型的转换***\n");
	CvPoint cv = cvPoint(678, 789);
	CvPoint2D32f cv1 = cvPointTo32f(cv);
	printf("\t原来的cvpoint数:%d,%d\n", cv.x, cv.y);
	printf("\t现在的cvpoint2d32f数:%f,%f\n", cv1.x, cv1.y);
	system("pause");
	return 0;
}

 

函数解析:

 

 

fabs() //取绝对值
cvRound() //对double型数据四舍五入后返回int型数据
cvGetTickCount() //返回64位长整数的时间数据,为CvRNG设置的专用种子。
cvRNG() //函数 cvRNG 初始化随机数生成器并返回其状态。指向这个状态的指针可以传递给函数 cvRandInt, cvRandReal 和 cvRandArr 
cvRandInt() //返回均匀分布的随机 32-bit 无符号整型值并更新 RNG 状态。
cvPointFrom32f() /*cvPoint转CvPoint2D32f
CV_INLINE  CvPoint  cvPointFrom32f( CvPoint2D32f point )
{
    CvPoint ipt;
    ipt.x = cvRound(point.x);
    ipt.y = cvRound(point.y);

    return ipt;
}
*/

cvPointTo32f() /*CvPoint2D32f转cvPoint
CV_INLINE  CvPoint2D32f  cvPointTo32f( CvPoint point )
{
    return cvPoint2D32f( (float)point.x, (float)point.y );
}
*/

 

 

 

第二题:

 

#include"cv.h"
#include"stdafx.h"
#include"highgui.h"

int _tmain(int argc, _TCHAR* argv[])
{
	CvMat* srcMat = cvCreateMat(100, 100, CV_8UC3);
	cvSetZero(srcMat);
	CvPoint cirPoint = cvPoint(50, 50);
	int r = 40;
	CvScalar circolor = cvScalar(25, 100,50);
	cvCircle(srcMat, cirPoint, r,circolor);
	cvNamedWindow("circle");
	cvShowImage("circle", (CvArr*)srcMat);
	cvWaitKey(0);
	cvReleaseMat(&srcMat);
	cvDestroyWindow("circle");
	return 0;
}

 

函数解析:

 

 

cvCreateMat( int rows, int cols, int type ); //创建一个矩阵,长*高(像素),以及类型CV_8UC3为8位无符号三通道
cvSetZero(srcMat); //清零矩阵
cvCircle( CvArr* img, CvPoint center, int radius,CvScalar color, int thickness CV_DEFAULT(1),
     int line_type CV_DEFAULT(8), int shift CV_DEFAULT(0));
/*画圆
载体矩阵,圆心坐标(像素),半径(像素),圆周颜色,半径粗细,圆周线的类型(见),圆心坐标点和半径值的小数点位数
*/

 

 

 

第三、四题:

 

#include"stdafx.h"
#include"cv.h"
#include"highgui.h"

int _tmain(int argc, _TCHAR* argv[])
{
	CvMat* mat = cvCreateMat(100, 100, CV_8UC3);
	cvSetZero(mat);
	//矩形平面
	for (int row = 20; row < 40; row++)
		for (int col = 5; col < 20; col++)
		{
			uchar* ptr = cvPtr2D((CvArr*)mat, row, col);
			ptr[1] = 255;
		}
	/*3_3为矩形,代替for循环里的内容
	uchar* ptr;
	for (int row = 20; row <= 40; row++)
		for (int col = 5; col <= 20; col++)
		{
			if (row == 20 || row == 40)
			{
				ptr = cvPtr2D((CvArr*)mat, row, col);
				ptr[1] = 255;
			}
			else
			{
				ptr = cvPtr2D((CvArr*)mat, row, 5);
				ptr[1] = 255;
				ptr = cvPtr2D((CvArr*)mat, row, 20);
				ptr[1] = 255;
			}
		}
	*/
	cvNamedWindow("green rectangle");
	cvShowImage("green rectangle", (CvArr*)mat);
	cvWaitKey(0);
	cvReleaseMat(&mat);
	cvDestroyWindow("green rectangle");
	return 0;
}

 

函数解析:

 

 

cvPtr2D( const CvArr* arr, int idx0, int idx1, int* type CV_DEFAULT(NULL) );
/*
返回一个uchar型的指向矩阵中元素的指针,idx0,idx1为索引的值,最后一个为可选参数,表示输出值的类型
*/

 

第五题:

 

#include"stdafx.h"
#include"cv.h"
#include"highgui.h"

int _tmain(int argc, _TCHAR* argv[])
{
	IplImage* img = cvCreateImage(cvSize(210, 210), 8, 1);
	cvZero(img);
	int hength = 210, width = 210, board = 10;
	int value = 0;
	for (int i=0,j=0; i<=200;)
	{
		cvSetImageROI(img, cvRect(i, j, width, hength));
		cvSet(img, cvScalar(value, 0, 0));
		cvResetImageROI(img);
		i += 10;
		j += 10;
		if (value<+255)
			value += 10;
	}
	cvNamedWindow("ROL");
	cvShowImage("ROL", img);
	cvWaitKey(0);
	cvReleaseImage(&img);
	cvDestroyWindow("ROL");
	return 0;
}

 

函数解析:

cvSetImageROI( IplImage* image, CvRect rect );
/*
选择特定的区域,与cvResetImageROI连用,所选取的特定区域在这两个函数之间有效。
两个参数:所要选取的图像以及选取的范围
*/
cvSet(CvArr* arr,CvScalar value);//设置矩阵的值
cvResetImageROI( IplImage* image );//取消选中

 

第六题:

 

#include"stdafx.h"
#include"cv.h"
#include"highgui.h"

int _tmain(int argc, _TCHAR* argv[])
{
	IplImage* img = NULL;//判断一下图像是否加载到
	img = cvLoadImage("board.jpg");
	IplImage* dst1, *dst2;
	dst1 = cvCreateImage(cvSize(20, 30), img->depth, img->nChannels);
	dst2 = cvCreateImage(cvSize(20, 30), img->depth, img->nChannels);
	dst1->origin = img->origin;
	dst1->widthStep = img->widthStep;
	dst2->origin = img->origin;
	dst2->widthStep = img->widthStep;
	dst1->imageData = img->imageData + img->widthStep * 10 + img->nChannels * 5;
	dst2->imageData = img->imageData + img->widthStep * 60 + img->nChannels * 50;
	cvNot(dst1, dst1);
	cvNot(dst2, dst2);

	cvNamedWindow("img");

	cvShowImage("img", img);

	cvWaitKey(0);

	cvReleaseImage(&img);
	cvReleaseImage(&dst1);
	cvReleaseImage(&dst2);

	cvShowImage("img", img);
	cvDestroyWindow("img");
	return 0;
}

 

 

 

函数解析:

 

 

cvNot( const CvArr* src, CvArr* dst ) //将原矩阵里的像素值取反,送到目标矩阵
/*
这里需要注意的是结构IplImage里的几个参数:
origin:选择坐标原点是在左上角还是左下角
widthStep:图像的行大小,以字节为单位,永远是四的倍数,不足的话自动补齐。
如程序中的img图像width = 640,nchannels = 3,一个通道是八位代表一个字节,因此widthstep = 640*3 = 1920个字节
imageData:指向图像数据的指针,默认指向图像的第(1,1)个像素

这里创建的两个图像头img,img2并没有正真的图像数据,他们的imgeData指针指向img的图像数据,因此他们会显示在img图像上。
*/

 

第七题:

 

#include"stdafx.h"
#include"cv.h"
#include"highgui.h"

int _tmain(int argc, _TCHAR* argv[])
{
	IplImage* src = cvLoadImage("board.jpg");
	IplImage* Rimag = cvCreateImage(cvGetSize(src), src->depth, 1);
	IplImage* Gimag = cvCreateImage(cvGetSize(src), src->depth, 1);
	IplImage* Bimag = cvCreateImage(cvGetSize(src), src->depth, 1);
	IplImage* clone1, *clone2;
	double G_MAX_PIX = 0;
	double G_MIN_PIX = 0;
	cvSplit(src, Rimag, Gimag, Bimag,NULL);//分离时的顺序到底是RGB还是BGR还不确定?

	clone1 = cvCloneImage(Gimag);
	clone2 = cvCloneImage(Gimag);

	cvMinMaxLoc(Gimag, &G_MIN_PIX, &G_MAX_PIX);

	double thresh = (unsigned char)(G_MAX_PIX - G_MIN_PIX) / 2.0;
	

	cvSet(clone1, cvScalar(thresh));
	cvSetZero(clone2);
	cvCmp(Gimag, clone1, clone2, CV_CMP_GE);
	cvSubS(Gimag, cvScalar(thresh / 2.0), Gimag, clone2);

	cvNamedWindow("src");
	cvNamedWindow("clone2");

	cvShowImage("src", src);
	cvShowImage("clone2", clone2);

	cvWaitKey(0);

	cvReleaseImage(&src);
	cvReleaseImage(&clone1);
	cvReleaseImage(&Rimag);
	cvReleaseImage(&Gimag);
	cvReleaseImage(&Bimag);
	cvReleaseImage(&clone2);


	cvDestroyWindow("src");
	cvDestroyWindow("clone2");
	return 0;
}

 

 

 

函数解析:

 

 

cvSplit( const CvArr* src, CvArr* dst0, CvArr* dst1,CvArr* dst2, CvArr* dst3 );
/*分离图像,分割多通道数组成几个单通道数组或者从数组中提取一个通道,目标图像只能是单通道*/
cvCloneImage( const IplImage* image ); /*克隆图像,函数自己会单独开一块内存,将复制的图像数据放进去
而cvCopy()则必须先创建一个图像*/
cvMinMaxLoc( const CvArr* arr, double* min_val, double* max_val,CvPoint* min_loc CV_DEFAULT(NULL),
             CvPoint* max_loc CV_DEFAULT(NULL),const CvArr* mask CV_DEFAULT(NULL) );
/*
	获取图像中像素值最大、最小的值以及他们的CPoint位置
*/

cvCmp( const CvArr* src1, const CvArr* src2, CvArr* dst, int cmp_op );
/*
	比较另个图像对应位置的像素值,如果条件为真,则结果矩阵对应位为0xff,否则为零。
	cmp_op有以下几种:
	CV_CMP_EQ (src1i == src2i)
	CV_CMP_GT (src1i > src2i)
	CV_CMP_GE (src1i >= src2i)
	CV_CMP_LT (src1i < src2i)
	CV_CMP_LE (src1i <= src2i)
	CV_CMP_NE (src1i != src2i)
*/
cvSubS( const CvArr* src, CvScalar value, CvArr* dst, const CvArr* mask CV_DEFAULT(NULL))
/*
将原图像每一个像素值减去一个值得到目标图像。
最后一个参数mask为矩阵开关:如果该矩阵非空,则dst将会与mask比较,对应mask中0元素的位置,在dst中不会被改变
*/

 

 

 

第八题:

 

#include"stdafx.h"
#include"cv.h"
#include"highgui.h"
#include"stdio.h"

typedef struct my_struct
{
	int i;
	CvPoint point;
	CvRect rect;
}Mystruct;

void write_my_struct(CvFileStorage* fs,const char* name, Mystruct* ms)
{
	cvStartWriteStruct(fs, name, CV_NODE_MAP);
	cvWriteInt(fs, "my_struct_value", ms->i);

	cvStartWriteStruct(fs, "my_struct_point", CV_NODE_SEQ);



	cvWriteInt(fs, 0, ms->point.x);
	cvWriteInt(fs, 0, ms->point.y);
	cvEndWriteStruct(fs);
	 
	cvStartWriteStruct(fs, "my_struct_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);

	cvEndWriteStruct(fs);
}

void read_my_stuct(CvFileStorage* fs, CvFileNode* ms_node, my_struct* ms)
{
	int i = cvGetFileNodeByName(fs, ms_node, "my_struct_value")->data.i;
	ms->i = i;

	CvSeq* s1 = cvGetFileNodeByName(fs, ms_node, "my_struct_point")->data.seq;
	CvPoint point;
	point.x = cvReadInt((CvFileNode*)cvGetSeqElem(s1, 0));
	point.y = cvReadInt((CvFileNode*)cvGetSeqElem(s1, 1));
	ms->point = point;

	CvSeq* s2 = cvGetFileNodeByName(fs, ms_node, "my_struct_rect")->data.seq;
	CvRect rect;
	rect.x = cvReadInt((CvFileNode*)cvGetSeqElem(s2, 0));
	rect.y = cvReadInt((CvFileNode*)cvGetSeqElem(s2, 1));
	rect.width = cvReadInt((CvFileNode*)cvGetSeqElem(s2, 3));
	rect.height = cvReadInt((CvFileNode*)cvGetSeqElem(s2, 2));
	ms->rect = rect;
}

void ShowStructValue(Mystruct* pvalue)
{
	printf("integer:%d\n", pvalue->i);
	printf("CvPoint: (%d, %d)\n", pvalue->point.x, pvalue->point.y);
	printf("CvRect: h-->%d\tw-->%d\t(%d, %d)\n", pvalue->rect.height,pvalue->rect.width, pvalue->rect.x, pvalue->rect.y);
}

int _tmain(int argc, _TCHAR* argv[])
{
	const char* filename = "example.xml";
	char name[12];
	CvFileStorage* fs = cvOpenFileStorage(filename, 0, CV_STORAGE_WRITE);
	for (int i = 0; i < 10; i++)
	{
		CvRNG rng = cvRNG(cvGetTickCount());
		int total = cvRandInt(&rng);
		my_struct ms = { total%256, cvPoint(total%512, total%233), cvRect(total%78, total%128, total%233, total%321)};
		sprintf(name, "mystruct%d", i);
		write_my_struct(fs, name, &ms);
	}
	cvReleaseFileStorage(&fs);
	
	fs = cvOpenFileStorage(filename, 0, CV_STORAGE_READ);
	my_struct ms1;
	for (int i = 0; i < 10; i++)
	{
		sprintf(name, "mystruct%d", i);
		CvFileNode* pnode = cvGetFileNodeByName(fs, NULL, name);
		read_my_stuct(fs, pnode, &ms1);
		ShowStructValue(&ms1);
	}
	cvReleaseFileStorage(&fs);
	system("pause");
	return 0;
}

 

函数解析:

 

 

cvStartWriteStruct()与cvEndWriteStruct()
/*在这两个函数之间写入结构体数据,当需要写入结构体的时候需要嵌套使用这两个函数,非结构体不需要
  这两个函数的使用使写入到文件里的数据层次分明。
  void cvStartWriteStruct(CvFileStorage* fs, const char* name, int struct_flags)
fs:文件存储器
name:为数据结构的名称
struct_flags:
		CV_NODE_SEQ - 被写入的数据结构为序列结构。这样的数据没有名称。
		CV_NODE_MAP - 被写入的数据结构为图表结构。这样的数据含有名称。
		以上两个必须二选一。
		CV_NODE_FLO 这个可选择标识符只能作用于YAML流。被写入的数据结构被看做一个数据流(不是数据块),它更加紧凑,当结构或数组里的数据是标量时,推荐用这个标志。
cvEndWriteStruct( CvFileStorage* fs );
		结束写结构体
*/

void cvWriteInt( CvFileStorage* fs, const char* name, int value );//向指定文件存储器写入整型数据,name为数据结构的名称

CvFileNode* cvGetFileNodeByName( const CvFileStorage* fs,const CvFileNode* map,const char* name );
/*
根据数据结构的名称获取结点,只由获取结点才能读取该结点下的数据。返回该数据的结点
fs:文件存储器
map:文件结点这里指父结点,没有的话为null
name:为数据结构的名称
*/

int cvReadInt( const CvFileNode* node, int default_value CV_DEFAULT(0) )//从结点读取整型数据

CvFileStorage* cvOpenFileStorage( const char* filename, CvMemStorage* memstorage,int flags, const char* encoding CV_DEFAULT(NULL) );
/*打开文件,返回文件存储器
flags:
	#define CV_STORAGE_READ          0
	#define CV_STORAGE_WRITE         1
*/

typedef struct CvFileNode
{
    int tag;
    struct CvTypeInfo* info; /* type information
            (only for user-defined object, for others it is 0) */
    union
    {
        double f; /* scalar floating-point number */
        int i;    /* scalar integer number */
        CvString str; /* text string */
        CvSeq* seq; /* sequence (ordered collection of file nodes) */
        CvFileNodeHash* map; /* map (collection of named file nodes) */
    } data;
}

cvGetSeqElem( const CvSeq* seq, int index );
/*根据所得seq得到seq表示结构体中的每一项数据,返回
char类型的指针,可以利用强制类型转换,转换为序列中实际存储的数据类型
data.i:表示取出整型数据
data.sep:b表示取出结构数据
*/
给出一次存储后文件中结构,方便理解,结构类似于树
<?xml version="1.0"?>
<opencv_storage>
<mystruct0>//最外层的结构名,为CV_NODE_MAP结构型
  <my_struct_value>32</my_struct_value>
  <my_struct_point>32 94</my_struct_point>
  <my_struct_rect>6 32 94 258</my_struct_rect>
</mystruct0>
</opencv_storage>


在画一幅图对应文件中的数据结构加强理解:

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值