Estadísticas de histograma de imagen de 8 bits ultra detalladas de C ++ y pantalla de dibujo, no use la función calcHist (), escriba estadísticas usted mismo

La función calcHist() provista en C++ OpenCv puede ayudarnos convenientemente a contar el histograma de una imagen de 8 bits, pero a veces no queremos usar la función provista por OpenCv para hacer estadísticas y queremos hacer estadísticas de acuerdo a nuestras propias necesidades. Después de aprender este método, no solo se pueden escribir a mano imágenes de 8 bits para estadísticas, sino que también se pueden escribir a mano imágenes de 10 bits, 12 bits, 14 bits, 16 bits, 24 bits, 32 bits y otras imágenes para realizar estadísticas de histograma y mostrarlas. Para obtener un tutorial específico sobre las estadísticas y la visualización de histogramas de imágenes de 16 bits, consulte mi próximo artículo.
El código para contar a mano el histograma de imágenes de 8 bits es el siguiente:

#include<opencv2/opencv.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include<iostream>

using namespace std;
using namespace cv;



int main()
{
	Mat image = imread("Images/16bit/8bit_3M_Lj/Original_3M_Lj.png", -1);  //输入8Bit图像
	

	Mat histogram = Mat::zeros(Size(256, 1), CV_32SC1);    	 //注意,Size对应的是x和y,也就是第一个元数是矩阵的列数。比如我这里创建的是256列1行的画布,即大小为1*255
	
	int rows = image.rows;   	 //输入图像的行数
	int cols = image.cols;		 //输入图像的列数

	for (int i = 0; i<rows; i++)
	{
		for (int j = 0; j<cols; j++)
		{
			int index = int(image.at<uchar>(i, j));	    //获取每个点的像素值
			histogram.at<int>(0, index) += 1;			//获取了一个像素值,在相应的位置上加1
		}
	}

	//开始直观的显示直方图——绘制直方图  
	//首先先创建一个黑底的图像,为了可以显示彩色,所以该绘制图像是一个8位的3通道图像,3通道图像画直方图的时候就可以画彩色的直方图了  
	Mat drawImage1 = Mat::zeros(Size(256, 400), CV_8UC3);   //这里是最后画直方图的地方,大小为400行,256列,这里画布的大小可以自定义

	//因为任何一个图像的某个像素的总个数,都有可能会有很多,会超出所定义的图像的尺寸,针对这种情况,先对个数进行范围的限制  
	//先用 minMaxLoc函数来得到计算直方图后的像素的最大个数  
	double g_dHistMaxValue;    //最大的像素值数目
	minMaxLoc(histogram, 0, &g_dHistMaxValue, 0, 0);

	//将像素的个数整合到 图像的最大范围内  
	//遍历直方图得到的数据  
	 
	for (int i = 0; i < 256; i++)
	{
		int value = cvRound(histogram.at<int>(0, i) * 256 * 1.4 / g_dHistMaxValue);   //这里公式中乘的1.4是为了使显示的直方图更高更好看一下,可以适当调整此值,自己看着舒服

		line(drawImage1, Point(i, drawImage1.rows - 1), Point(i, drawImage1.rows - 1 - value), Scalar(255, 255, 0));   //以线条的方式来绘画直方图
		//rectangle(drawImage1, Point(i, drawImage1.rows - 1), Point(i, drawImage1.rows - 1 - value), Scalar(255, 255, 0));  //以矩形框的方式绘画直方图,这里和上面的显示方式任意一种都可以
	}

	imshow("图像直方图", drawImage1);


	cout << "histogram = " << histogram;



	waitKey();
	return 0;
}

La imagen original del código anterior ejecutándose se muestra a continuación. Puede descargar la imagen y ejecutar el código para echar un vistazo.
Nota : la entrada de imagen original aquí es una imagen en escala de grises de un solo canal. Puede procesar imágenes de varios canales secuencialmente a través de la división de canales, y también puede contar el código usted mismo.
inserte la descripción de la imagen aquí

Los resultados de la ejecución del código anterior son los siguientes:
inserte la descripción de la imagen aquí
El histograma estadístico final es:
inserte la descripción de la imagen aquí
Para verificar el código que hice a mano y contar el histograma de la imagen de 8 bits, lo siguiente utiliza la función calcHist() proporcionada por OpenCv para comparar las estadísticas de la misma imagen, así es el código de la función calcHist() estadísticas proporcionadas por OpenCv:

#include<opencv2/opencv.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include<iostream>

using namespace std;
using namespace cv;

void show_histogram(Mat& img)
{
	//为计算直方图配置变量  
	//首先是需要计算的图像的通道,就是需要计算图像的哪个通道(bgr空间需要确定计算 b或g货r空间)  
	int channels = 0;
	//然后是配置输出的结果存储的 空间 ,用MatND类型来存储结果  
	MatND dstHist;
	//接下来是直方图的每一个维度的 柱条的数目(就是将数值分组,共有多少组)  
	int histSize[] = { 256 };       //如果这里写成int histSize = 256;   那么下面调用计算直方图的函数的时候,该变量需要写 &histSize  
	//最后是确定每个维度的取值范围,就是横坐标的总数  
	//首先得定义一个变量用来存储 单个维度的 数值的取值范围  
	float midRanges[] = { 0, 256 };
	const float *ranges[] = { midRanges };

	calcHist(&img, 1, &channels, Mat(), dstHist, 1, histSize, ranges, true, false);

	//calcHist  函数调用结束后,dstHist变量中将储存了 直方图的信息  用dstHist的模版函数 at<Type>(i)得到第i个柱条的值  
	//at<Type>(i, j)得到第i个并且第j个柱条的值  

	//开始直观的显示直方图——绘制直方图  
	//首先先创建一个黑底的图像,为了可以显示彩色,所以该绘制图像是一个8位的3通道图像  
	Mat drawImage = Mat::zeros(Size(256, 400), CV_8UC3);
	//因为任何一个图像的某个像素的总个数,都有可能会有很多,会超出所定义的图像的尺寸,针对这种情况,先对个数进行范围的限制  
	//先用 minMaxLoc函数来得到计算直方图后的像素的最大个数  
	double g_dHistMaxValue;    //最大的像素值数目
	minMaxLoc(dstHist, 0, &g_dHistMaxValue, 0, 0);
	//minMaxLoc(hist, &minValue, &maxValue, 0, 0);//找到全局最小、最大的像素值数目
	//将像素的个数整合到 图像的最大范围内  
	//遍历直方图得到的数据  
	for (int i = 0; i < 256; i++)
	{
		int value = cvRound(dstHist.at<float>(i) * 256 * 1.4 / g_dHistMaxValue);

		line(drawImage, Point(i, drawImage.rows - 1), Point(i, drawImage.rows - 1 - value), Scalar(255, 255, 0));
	}

	imshow("直方图统计", drawImage);
}

int main()
{
	//Mat image = imread("Images/16bit/8bit_3M_Lj/16bitZhiFanTuJunHen_PinTai_3M_Lj(7).png", -1);
	Mat image = imread("Images/16bit/8bit_3M_Lj/Original_3M_Lj.png", -1);   //输入8Bit图像
	//Mat image = imread("Images/16bitwhq.png", -1);
	show_histogram(image);

	
	waitKey();
	return 0;
}

Los resultados de las estadísticas del histograma de la imagen usando la función calcHist() proporcionada por OpenCv son los siguientes:
inserte la descripción de la imagen aquí
De la comparación anterior, se puede ver que los resultados estadísticos del código que escribí y los resultados del histograma usando la función calcHist() proporcionada por OpenCv son consistentes, se verifica que mi método sin la función calcHist() proporcionada por OpenCv es factible.

Lo anterior es el proceso detallado de contar el histograma de la imagen de 8 bits a través del código a mano. Para las estadísticas del histograma de la imagen de 16 bits, consulte mi próximo artículo. Si este método es útil para usted, por favor dele me gusta y anímelo, gracias ¡tú!

Supongo que te gusta

Origin blog.csdn.net/qq_40280673/article/details/124324942
Recomendado
Clasificación