OpenCV2.3的cvCalcHist函数有问题?255级值总为0,索性自己写一个直方图计算函数,附源码!

欢迎大家加入图像识别技术交流群:271891601,另外,特别欢迎成都从事图像识别工作的朋友交流,我的QQ号248787278

-------------------------------------------

我在写直方图规定化的代码过程中,发现OpenCV自带的cvCalcHist函数计算出的直方图的第255分量总是为0,测试了几张图都是这样,代码如下:

#include <opencv2/opencv.hpp>
#include <opencv2/legacy/compat.hpp>
#include <fstream>
using namespace std;
#pragma comment(linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"")  

CvHistogram* CreateGrayImageHist(IplImage **ppImage)
{
    int nHistSize = 256;  //这句话表明有256个灰度级
    float fRange[] = {0, 255};  //灰度级的范围是0到255
    float *pfRanges[] = {fRange};   //下一句使用的cvCreateHist函数要求第四个参数是指针的指针,
								    //所以要作这样的处理,至于为什么要用指针的指针,我也不清楚
    CvHistogram *pcvHistogram = cvCreateHist(1, &nHistSize, CV_HIST_ARRAY, pfRanges); //在使用直方图计算函数cvCalcHist前,
																					  //需要先创建cvCalcHist的第二个参数需要数据类型
    cvCalcHist(ppImage, pcvHistogram);//直方图计算函数cvCalcHist,注意第一个参数要求是指针的指针,具体为什么要这样,我也不清楚
				       //至于怎么取用存放在pcvHistogram中的直方图数据,看完下面的main函数就知道了
    return pcvHistogram;
}  

int main()

{
	IplImage *a = cvLoadImage("coins.png", CV_LOAD_IMAGE_UNCHANGED);

	CvHistogram *a_hist = CreateGrayImageHist(&a);// CreateGrayImageHist是自己写的函数哦

	int index;
	double watch_a_hist[256];
	for (index = 0; index<256; index++)
	{
		 watch_a_hist[index] = cvQueryHistValue_1D(a_hist,index);
	}

return 0;
}

和MATLAB运行结果的对比截图如下:

于是自己写了一个直方图计算函数,经测试,无误 ,代码如下:

void mycvCalcHist(IplImage *img,double out_hist[256])
{
	int i=0, j=0;
	double temp1=0;
	int temp2=0;
    const int hist_sz = 256;//0到255,一共256个灰度值
    double hist[hist_sz];
    memset(hist, 0, sizeof(hist));
    for( i = 0; i < img->height; i++ )
    {
        for( j = 0; j < img->width; j++ )
		{	temp1=cvGet2D(img,i,j).val[0];
			temp2=int(temp1);//作类型转换
            hist[temp2]++; //这里实现了hist中存储各灰度值出现的次数
		}
    }  

	memcpy(out_hist,hist, sizeof(hist)); //肯定有人要问,为啥不用数组名作为参数传递从而改变实参数组的值
										 //这种方法一般情况下都可以,我也测试了,然而这里就是不行,我估计与
										 //memset(hist, 0, sizeof(hist));这句语句有关

}

int main()
{
	IplImage *a = cvLoadImage("coins.png", CV_LOAD_IMAGE_UNCHANGED);  

	double a_hist[256];

	mycvCalcHist(a,a_hist);

return 0;
}

补充说明一下为啥用double类型的数组,因为直方图数据经常要参与浮点数运算,所以干脆用这个!

时间: 2024-08-25 03:51:50

OpenCV2.3的cvCalcHist函数有问题?255级值总为0,索性自己写一个直方图计算函数,附源码!的相关文章

根据MATLAB的histeq函数改写的运行在OpenCV下的直方图规定化C源码!

据说,图像的直方图规定化比直方图均衡化用得更多,但是很奇怪的是OpenCV居然没有图像直方图规定化的源码!所以,我就有必要在OpenCV下写一个图像直方图规定化处理的函数,以方便将来使用. 我在网上找了几个直方图均稀化的源码,并基于OpenCV来改写这些源码,效果都不如MATLAB的histeq函数,这其中改写的艰辛与繁琐就不细说了.最后,没办法,只好学习MATALB的histeq函数源码,并对其进行基于OpenCV的改写. 虽然我最终改写成功了,但是对算法还是不太理解,只能按照MATLAB的帮

Matlab.NET混合编程技巧之——直接调用Matlab内置函数(附源码)

原文:[原创]Matlab.NET混合编程技巧之--直接调用Matlab内置函数(附源码) 在我的上一篇文章[原创]Matlab.NET混编技巧之--找出Matlab内置函数中,已经大概的介绍了matlab内置函数在混合编程中的优点,并通过程序找出了matlab中的大部分内置函数,当然更多人关心是如何像我所说得那样,不用直接编译,就直接在C#中调用这些内置函数.本文就带你揭开这些谜团. 声明,这篇文章是需要一点点混合编程基础的,基本概念和过程要懂一点,如果能简单成功混编一个简单的计算或者绘图例子

10.1 优化函数 在前面的章节中,我们已经知道,递归是 F# 中处理函数的主要控制流机制。我们第一次是使用它写一些进行计算的简单函数,例如,计算指定范围内的数字的和或阶乘。后来,我们发现它在处理递

10.1 优化函数 在前面的章节中,我们已经知道,递归是 F# 中处理函数的主要控制流机制.我们第一次是使用它写一些进行计算的简单函数,例如,计算指定范围内的数字的和或阶乘.后来,我们发现它在处理递归数据结构,最重要的列表是时,是无价的. 我们知道,递归也有一些局限性,堆栈溢出的可能性是最明显的一个:我们将会看到,某些递归计算非常低效.在命令式语言中,通常使用非递归函数,以避免出现问题:函数语言已经有方法解决这些问题,并可以高效地使用递归.首先要集中关注于正确性:如果一个额外的字节吹动堆栈,真正

写一个求和的函数sum

写一个求和的函数sum,达到下面的效果 // Should equal 15 sum(1, 2, 3, 4, 5); //Should equal 0 sum(5, 'abc', -5); //Should equal 4 sum(1, true, 'a', 'D', 1, 'F', 1, 'w'): 下面附上多种方法: function sum(){ var add = 0; for(var i = 0; i < arguments.length; i++){ if(!isNaN(Number

写一个字符串反转函数,实现字符串倒序。

第一种方法: <script type="text/javascript">var str="abcdeg";function demo(str){var str2="";for(var i=0;i<str.length;i++){str2+=str.charAt(str.length-i-1);} document.write(str+"<br />"+str2)}demo(str);</

写一个事件封装函数

var EventHandle = { addEvent:function(ele,type,handle){ if (ele.addEventListener) { ele.addEventListener(type,handle,false); }else if(attachEvent){ ele.attachEvent("on"+type,handle); }else{ ele["on"+type]=handle; } }, deleteEvent:funct

为LoadRunner写一个lr_save_float函数

LoadRunner中有lr_save_int() 和lr_save_string() 函数,但是没有保存浮点数到变量的lr_save_float函数.<lr_save_float() function for LoadRunner>这篇文章介绍了如何写一个这样的函数: http://ptfrontline.wordpress.com/2010/01/27/lr_save_float-function-for-loadrunner/ void lr_save_float(const float

关于追踪qemu 源码函数路径的一个方法

这阵子一直在研究qemu 磁盘io路径的源码,发现直接看代码是意见非常低效率的事情,qemu是一个比较庞大的家伙(源码部分大概154MB,完全由C语言来完成),整个结构也都非常地复杂,所以从代码上研究qemu最好的办法只有debug之.不断地收集更多的debug信息去获取源码所蕴含的道理. 很多人第一反应可能就是使用一些类似与Eclipse, gdb 这一类强大的debugger,我当然也不例外,在经过一个上午究竟该使用Eclipse还是gdb的思想斗争的私人情绪之后,我才恍然明白,原来我两个工

ZeroMQ接口函数之 :zmq_socket_monitor - 注册一个监控回调函数

ZeroMQ 官方地址 :http://api.zeromq.org/4-2:zmq-socket-monitor zmq_socket_monitor(3) ØMQ Manual - ØMQ/4.1.0 Name zmq_socket_monitor - 注册一个监控回调函数 Synopsis int zmq_socket_monitor (void *socket, char * *addr, int events); Description zmq_socket_monitor() 函数会