java 灰度直方图_图像的灰度直方图

本文介绍如何使用Java实现图像的灰度直方图计算与绘制。通过直方图结构体CvHistogram,创建直方图并进行计算,接着利用直方图数据绘制出每个通道(BGR)的直方图。最后展示如何归一化直方图并显示图像直方图。
摘要由CSDN通过智能技术生成

1、一维直方图:单通道,bin是一条直线

二维直方图:双通道,bin是一个矩形

2、直方图的结构体:CvHistogram

typedef struct CvHistogram

{

int  type;

CvArr*  bins; 存放直方图在每一维上直方柱的具体数据,由于存在多维直方图。如果是一维直方图,那么bins就是一个一维  的矩阵;如果是二维直方图,那么bins就是一个二维的矩阵,等等。

float   thresh[CV_MAX_DIM][2]; /* 直方柱的划分 是统一划分的,即均等划分的 */

float** thresh2; /*不均等划分,可以自动设定每一个直方柱的取值范围。之所以是二级指针,每一个柱的取值范围用一级指针表示,又存在多个直方柱,所以需要二级指针才能表示。每一个不在指定范围的值,会被忽略掉。*/

CvMatND mat; /* 存放直方图的数据 */

}

3、CvHistogram* cvCreateHist( int dims, int* sizes, int type,float** ranges=NULL, int uniform=1 ); 创建一个直方图的函数

dims:表示直方图的维度

sizes:每一维上直方柱(bin)的数据

type:直方图存储数据的方式:CV_HIST_ARRAY 意味着直方图数据表示为多维密集数组CvMatND; CV_HIST_TREE 意味着直方图数据表示为多维稀疏数组CvSparseMat.

ranges:直方图在每一维度上的范围。

uniform:存每一维的坐标的取值范围。该值为0时,表示bin的范围是程序员自由设定的。当该值为非零时,表示bin的划分,是均等划分。

注:在创建完一个直方图后,必须调用cvClearHist(hist)函数,去掉一些不必要的随机值

4、给某个通道分配相应的空间:IplImage* b_img=cvCreateImage(cvGetSize(img),8,1);

5、cvSplit(img,b_img,g_img,r_img,NULL);  把图img像分解成四个通道,且这三个通道的顺序必须是B、G、R

6、计算每一个通道的直方图,即每个通道上的每个直方柱的大小(高度):cvCalcHist(&b_img,hist,0,0);   //计算b_img这个通道的直方图的大小,结果存在hist里面

7、找出htist这个直方图里面哪个直方柱的值最大,并将该最大值存在histmax里面,为了做归一化:

float histmax=0;       cvGetMinMaxHistValue(hist,0,&histmax,0,0);

8、获取直方图hist里边第i个bin的值:float pt=cvQueryHistValue_1D(hist,i);

// 图像的灰度直方图.cpp : Defines the entry point for the console application.

#include "stdafx.h"

#include "cv.h"

#include "highgui.h"

#include "cxcore.h"

IplImage* DrawHistogram(CvHistogram* hist,int scaleX=1,int scaleY=1)

{

float histmax=0;

cvGetMinMaxHistValue(hist,0,&histmax,0,0);

IplImage* histImg=cvCreateImage(cvSize(256*scaleX,64*scaleY),8,1);

cvZero(histImg);

for(int i=0;i<255;i++)

{

float pt=cvQueryHistValue_1D(hist,i); //获取直方图hist里边第i个bin的值

float pt_next=cvQueryHistValue_1D(hist,i+1); //获取直方图hist里边第i+1个bin的值

CvPoint pt1=cvPoint(i*scaleX,64*scaleY); //第i个点的坐标

CvPoint pt2=cvPoint((i+1)*scaleX,64*scaleY); //第i+1个点的坐标

CvPoint pt3=cvPoint((i+1)*scaleX,(64-pt_next/histmax*64)*scaleY); //归一化

CvPoint pt4=cvPoint(i*scaleX,(64-pt/histmax*64)*scaleY);

CvPoint pts[5];

int numPts=5;

pts[0]=pt1;

pts[1]=pt2;

pts[2]=pt3;

pts[3]=pt4;

pts[4]=pt1;

//不能直接这样子赋值:CvPoint pts[5]={pt1,pt2,pt3,pt4,pt5};

cvFillConvexPoly(histImg,pts,numPts,cvScalar(255)); //填充由这四个点构成的矩形

}

return histImg;

}

int main(int argc, char* argv[])

{

IplImage* img=cvLoadImage("E:\\大四上\\openCV\\图片\\机器猫.jpg");

IplImage* b_img=cvCreateImage(cvGetSize(img),8,1); //单通道图像

IplImage* g_img=cvCreateImage(cvGetSize(img),8,1);

IplImage* r_img=cvCreateImage(cvGetSize(img),8,1);

int dims=1; //直方图的维度

int size=256;

float range[]={0,255};

float *ranges[]={range}; //取值范围

CvHistogram* hist=cvCreateHist(dims,&size,CV_HIST_ARRAY,ranges,1); //创建一个直方图

cvClearHist(hist); //清除直方图,去掉一些不必要的随机值

cvSplit(img,b_img,g_img,r_img,NULL); //把图像分解成四个通道

cvCalcHist(&b_img,hist,0,0); //计算b_img这个通道的直方图的大小,结果存在hist里面

b_img=DrawHistogram(hist);

cvNamedWindow("b_img");

cvShowImage("b_img",b_img);

cvClearHist(hist);

cvCalcHist(&g_img,hist,0,0); //计算b_img这个通道的直方图的大小,结果存在hist里面

g_img=DrawHistogram(hist);

cvNamedWindow("g_img");

cvShowImage("g_img",g_img);

cvClearHist(hist);

cvCalcHist(&r_img,hist,0,0); //计算b_img这个通道的直方图的大小,结果存在hist里面

r_img=DrawHistogram(hist);

cvNamedWindow("r_img");

cvShowImage("r_img",r_img);

cvClearHist(hist);

cvWaitKey(0);

//(1) 释放源图像

cvReleaseImage(&img);

//(2) 释放三个通道的图像

cvReleaseImage(&r_img);

cvReleaseImage(&g_img);

cvReleaseImage(&b_img);

//(4)释放直方图空间

cvReleaseHist(&hist);

return 0;

}

52d62b2b8bdc07c2b65595f5bdbb5694.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值