(一)OpenCV图像处理基础_23_直方图计算

本文介绍了OpenCV中的图像直方图计算基础知识,不仅限于像素灰度直方图,还涵盖图像的其他属性值。直方图的特征包括维度(dims)、子区域大小划分(bins,通常为256级)和值的范围([0, 255])。" 113474319,10565592,UkeySoft CD DVD Encryption: 光盘加密与安全工具,"['数据安全', '加密工具', '光盘工具', '虚拟驱动器', '文件管理']
摘要由CSDN通过智能技术生成
  1. 一般直方图概念是基于图像像素值,其实对图像梯度、每个像素的角度、等一切图像的属性值,我们都可以建立直方图。
    这个才是直方图的概念真正意义,不过是基于图像像素灰度直方图是最常见的。
  2. 直方图最常见的几个属性:
    dims 表示维度,对灰度图像来说只有一个通道值dims=1
    bins 表示在维度中子区域大小划分,bins=256,划分为256个级别(0-255总共256个区域)
    range 表示值得范围,灰度值范围为[0~255]之间
split// 把多通道图像分为多个单通道图像
(
const Mat &src, //输入图像
Mat* mvbegin)// 输出的通道图像数组
calcHist//从数据创建直方图
(
 const Mat* images,//输入图像指针
int images,// images中包含的数组个数
const int* channels,//通道数
InputArray mask,// 输入mask,可选,不用
OutputArray hist,//输出的直方图数据
int dims,// 维数
const int* histsize,// 直方图级数,hist sizes in each dim
const float* ranges,// 值域范围,'dims' pairs set bin sizes
bool uniform,// true for uniform binning
bool accumulate//add to 'hist' else replace
)
#include <opencv2/opencv.hpp>
#include <iostream>

using namespace std;
using namespace cv;

int main(int argc, char** argv)
{
	Mat src;
	src = imread("../path.jpg");
	if (src.empty())
	{
		cout << "could not load image..." << endl;
		return -1;
	}

	namedWindow("src", WINDOW_AUTOSIZE);
	imshow("src", src);

	//多通道显示
	vector<Mat> dst;//可以用稀疏矩阵SparseMat类型来表示直方图
	//多通道矩阵→多个单通道矩阵
	split(src, dst);
	//namedWindow("dst", WINDOW_AUTOSIZE);
	//imshow("dst", dst[0]);

	//计算直方图
	int histSize = 256;//每个维度中的区间的个数
	float ranges[] = { 0 ,256 };//ranges范围,uniform为true,下界包含,上界不包含/uniform为false,下界包含,(上界-1)不包含
	const float *histRanges = { ranges };//histSize每个区间对应的值由ranges来指定
	Mat b_hist, g_hist, r_hist;
	
	//从数据创建直方图,可以从一个或多个数组中创建直方图
	calcHist(&dst[0], //Mat* images
		1,//上个参数(images)中包含的数组个数
		0,//在计算直方图时,使用输入数据中的哪些参数
		Mat(),//掩膜,用来选择images中每个数组中哪些像素与直方图的计算
		b_hist,//直方图计算的输出值
		1,//输出直方图的维度
		&histSize,//每个维度中的区间的个数 /const float** histSize//hist sizes in each dim
		&histRanges,//histSize每个区间对应的值由ranges来指定//'dims' pairs set bin sizes
		true,//uniform//ranges[i]表示第i维中区间的结构,如果uniform为true,那么第i维中所有的区间都等长,如果uniform为false,假如第i维中有n个bins,那么ranges[i]中必须有n个元素
		false);//告诉opencv从images得到的数据被累加进入hist之前,不要将其中的元素删除,重新分配或是设置为0
	calcHist(&dst[1], 1, 0, Mat(), g_hist, 1, &histSize, &histRanges, true, false);
	calcHist(&dst[2], 1, 0, Mat(), r_hist, 1, &histSize, &histRanges, true, false);

	// 归一化
	int hist_h = 400;//直方图的高度,假设为400
	int hist_w = 512; //直方图的宽度 256 *2

	Mat histImage(hist_w, hist_h, CV_8UC3, Scalar(0, 0, 0));//定义直方图矩阵
	//把输出的直方图范围元素(主要是直方图高度) 映射到(0,hist_h)即(0,400)
	normalize(b_hist, b_hist, 0, hist_h, NORM_MINMAX/*映射到区间[0, hist_h]*/, -1/*深度*/, Mat());
	normalize(g_hist, g_hist, 0, hist_h, NORM_MINMAX, -1, Mat());
	normalize(r_hist, r_hist, 0, hist_h, NORM_MINMAX, -1, Mat());

	//绘制直方图
	int bin_w = hist_w / histSize;//维度中子区域大小划分 =  直方图的宽度 / 每个维度中的区间的个数
	for (int i = 1; i < histSize; i++) 
	{
			line(histImage,//绘制在Mat histImage
				Point((i - 1)*bin_w, hist_h - cvRound(b_hist.at<float>(i - 1))),//第一个点
				Point((i)*bin_w, hist_h - cvRound(b_hist.at<float>(i))), //第二个点
				Scalar(255, 0, 0), //颜色
				2,//线宽
				LINE_AA);//高斯抗锯齿

			line(histImage, Point((i - 1)*bin_w, hist_h - cvRound(g_hist.at<float>(i - 1))),
				Point((i)*bin_w, hist_h - cvRound(g_hist.at<float>(i))), Scalar(0, 255, 0), 2, LINE_AA);

			line(histImage, Point((i - 1)*bin_w, hist_h - cvRound(r_hist.at<float>(i - 1))),
				Point((i)*bin_w, hist_h - cvRound(r_hist.at<float>(i))), Scalar(0, 0, 255), 2, LINE_AA);
	}
	namedWindow("Histogram", WINDOW_AUTOSIZE);
	imshow("Histogram", histImage);

	waitKey(0);
	return 0;
}

输出结果:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值