opencv学习笔记之四 c++和直方图

<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">1.内联函数 inline关键字 在编译的时候编译器会替换函数名为函数体,避免了函数调用需要现场和返回指针。利用增加内存占用来提高效率。 </span>

2.重载函数依据形参来区别,编译器会根据形参的不同调用最合适的函数。放回值类型不能区分重载。typeof定义的也不行。不同参数的传递方式(传值和传址)也不行。

int max(int a,int b)
int max(int a,int b,int c)
double max(double a,double b)
float max(float a,float b)
double max(int a,double b)
int sum(int a)      //传值
int sum(int& a)     //传址
3.函数指针

int maxvalue(int a,int b);
int (*p) (int,int);  //形参可以省略
……
p = maxvalue;     //指向
max = (*p)(4,5);  //调用方式
……

4.链表和数组的差别

摘自百度知道

二者都属于一种数据结构
从逻辑结构来看
1. 数组必须事先定义固定的长度(元素个数),不能适应数据动态地增减的情况。当数据增加时,可能超出原先定义的元素个数;当数据减少时,造成内存浪费;数组可以根据下标直接存取。
2. 链表动态地进行存储分配,可以适应数据动态地增减的情况,且可以方便地插入、删除数据项。(数组中插入、删除数据项时,需要移动其它数据项,非常繁琐)链表必须根据next指针找到下一个元素
从内存存储来看
1. (静态)数组从栈中分配空间, 对于程序员方便快速,但是自由度小
2. 链表从堆中分配空间, 自由度大但是申请管理比较麻烦 

从上面的比较可以看出,如果需要快速访问数据,很少或不插入和删除元素,就应该用数组;相反, 如果需要经常插入和删除元素就需要用链表数据结构了。


5.当全局变量和局部变量同名时,在块内的局部变量优先级高。使用作用域运算符“::”来访问全局变量。

z = ::x + ::y;

static int m,n = 3;  //静态(局部/全局)变量

//静态(局部)变量

存储在内存的静态存储区;在调用之后变量保留原来的内存空间和值,但只能被定义它的函数调用;一般在声明处初始化,默认初始化0。

//静态(局部/全局)变量

为了局限变量只被本文件(XX.cpp)使用。

存储在内存的静态存储区;一般在声明处初始化,默认初始化0。在文件之外不可见。


static int add(int m,int n){
	return m + n;
}    //内部函数只能被文件内的函数调用。
避免不同文件之间的互相干扰。增强可移植性。
extern int add(int m,int n){
	return m + n;
}    //外部函数

6.堆栈

是两种数据结构。堆:先进先出,由程序员申请,由程序员/OS释放;栈:先进后出,由系统分配。


//==============      OpenCV   直方图      =================

参数讲解:

1.cvHistgram()

typedef struct CvHistogram
{
<span style="white-space:pre">	</span>int type;
<span style="white-space:pre">	</span>CvArr* bins;
<span style="white-space:pre">	</span>float thresh[CV_MAX_DIM][2]; /* for uniform histograms */
<span style="white-space:pre">	</span>float** thresh2; /* for non-uniform histograms */
<span style="white-space:pre">	</span>CvMatND mat; /* embedded matrix header for array histograms */
}
CvHistogram;


//*****一维直方图:

bin表示在灰度范围(0-255之间划分的均匀的小段的范围)      bin是一维矩阵

int bin = 256,表示划分256个bin,每一个bin的(长度)就是1,范围是0-1;1-2;2-3;……以此类推

直方图需要统计图像的像素点落在每一个不同范围的bin中的数量。

//*****二维直方图:

每一个bin的范围变成了面:0<X<1,0<Y<1,以此类推。          bin是二维矩阵(三维/四维……)


2.cvCreateHist()

CVAPI(CvHistogram*)  cvCreateHist( int dims, int* sizes, int type,
                                   float** ranges CV_DEFAULT(NULL),
                                   int uniform CV_DEFAULT(1));


//dims  维数
//sizes  几维的就存几个值  为了创建矩阵(多大)    一维的图像且bin=6,则创建一个1X6的矩阵用来存放bin中的数值  size[0] = 6
//     二维的 且X,Y的维数是4,则创建一个4X4的矩阵用来存放bin中的数值 size[0] = 4;size[1] = 4;

//ranges  为了创建矩阵(什么类型)1 密集型矩阵bin 1x1   CV_HIST_ARRAY  0 ;    2稀疏型矩阵  效率高,高维选用  CV_HIST_SPARSE  1。

//uniform   !=0  则均等划分

 

// opencv11.cpp : 定义控制台应用程序的入口点。
//B G R

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

IplImage* DrowHistogram(CvHistogram* hist,int scaleX =1,int scaleY =1)
{
	float histMax = 0;
	cvGetMinMaxHistValue(hist,0,&histMax,0,0);
	IplImage* imghist = cvCreateImage(cvSize(256*scaleX,64*scaleY),8,1); 
	cvZero(imghist);//置0
	int i = 1;
	for(i = 1;i<255;i++)
	{
		float histvalue = cvQueryHistValue_1D(hist,i);//1维
		float nextvalue = cvQueryHistValue_1D(hist,i+1);
		CvPoint pt1 = cvPoint(    i*scaleX,64*scaleY);
		CvPoint pt2 = cvPoint((i+1)*scaleX,64*scaleY);
		CvPoint pt3 = cvPoint((i+1)*scaleX,(int)(64-(nextvalue/histMax)*64)*scaleY);
		CvPoint pt4 = cvPoint(    i*scaleX,(int)(64-(histvalue/histMax)*64)*scaleY); 
		int numPts = 5;
		CvPoint pts[5];
		pts[0] = pt1;
		pts[1] = pt2;
		pts[2] = pt3;
		pts[3] = pt4;
		pts[4] = pt1;
		cvFillConvexPoly(imghist , pts, numPts,cvScalar(255));  //五点四边形

	}
	return imghist;

}

int _tmain(int argc, _TCHAR* argv[])
{
	IplImage* img;
	img = cvLoadImage("D:\\PERSONAL\\VC++\\OpenCV\\image\\hy4.jpg");
	
	int sizes = 256/1;  //对每个值都要统计像素点个数  如果bin的长度是5,则为256/5
						//如果是二维的,sizes是一个二维数组   size[2] = {256,4}
	int dims  = 1;   //维数
	float range[] = {0,255};//统计的范围是0-255    range[] = {30-255}  0-29不计
	float* ranges[] = {range};
	CvHistogram* hist = cvCreateHist(dims,&sizes,CV_HIST_ARRAY,ranges,1);//均等
	cvClearHist(hist);  //清除生成hist时的可能的系统赋值
	IplImage* imgRed = cvCreateImage(cvGetSize(img),8,1);//8位
	IplImage* imgGreen = cvCreateImage(cvGetSize(img),8,1);
	IplImage* imgBlue = cvCreateImage(cvGetSize(img),8,1);
	
	//把原图像分为四个单通道  四缺省
	cvSplit(img,imgBlue,imgGreen,imgRed,NULL);

	//计算直方图 得到矩阵 存具体每个bin中的值
	cvCalcHist(&imgBlue,hist,0,0);  //统计imgBlue,把值放在hist中
	IplImage* hist_b = DrowHistogram(hist,2,2);//注意顺序
	cvClearHist(hist); //清除矩阵。
	
	cvCalcHist(&imgGreen,hist,0,0);
	IplImage* hist_g = DrowHistogram(hist);  //默认值是1 1
	cvClearHist(hist);

	cvCalcHist(&imgRed,hist,0,0);
	IplImage* hist_r = DrowHistogram(hist);
	cvClearHist(hist);

	cvNamedWindow("B");cvNamedWindow("G");cvNamedWindow("R");cvNamedWindow("hy4");
	cvShowImage("B",hist_b);cvShowImage("G",hist_g);cvShowImage("R",hist_r);cvShowImage("hy4",img);

	cvWaitKey(0);

	cvReleaseImage(&hist_b);cvReleaseImage(&hist_g);cvReleaseImage(&hist_r);cvReleaseImage(&img);
	cvDestroyWindow("B");cvDestroyWindow("G");cvDestroyWindow("R");cvDestroyWindow("hy4");

	return 0;
}

解说如下,首先视频中的代码计算的其实是直方图的补集。计算的数据类型的警告修改如上。










你可能感兴趣的:(opencv)