jashliao 用 VC++ 實現 fanfuhan OpenCV 教學017 ~ opencv-017-計算/顯示 彩色/灰階 對應的直方圖

jashliao 用 VC++ 實現 fanfuhan OpenCV 教學017 ~ opencv-017-計算/顯示 彩色/灰階 對應的直方圖

jashliao 用 VC++ 實現 fanfuhan OpenCV 教學017 ~ opencv-017-計算/顯示 彩色/灰階 對應的直方圖


資料來源: https://fanfuhan.github.io/

https://fanfuhan.github.io/2019/03/28/opencv-017/


GITHUB:https://github.com/jash-git/fanfuhan_ML_OpenCV

https://github.com/jash-git/jashliao-implements-FANFUHAN-OPENCV-with-VC


★前言:


★主題:

    圖片直方圖:
        圖像像素值的特徵、細節、細節豐富、旋轉、縮放不變性等特點,廣泛地深入處理的各個領域,特別是圖像圖像的高分辨率特徵、基於 顏色的圖像檢索以及圖像分類、背部投影。常見的分為
            灰階直方圖
            顏色(彩色)直方圖

        bins是指直方值取值的大小範圍,對於直方像素取值在0~2555之間的,最少有256個bin,此外還可以有16、32、48、128等,256除以bin的大小應該是罐子 倍。

    OPENCV計算直方圖函數(calcHist),其介紹如下所列:
        void calcHist( const Mat* images, int nimages,const int* channels, InputArray mask,OutputArray hist, int dims, const int* histSize,const float** ranges, bool uniform=true, bool accumulate=false );
            1.輸入的圖像數組   
            2.輸入數組的個數
            3.通道數
            4.掩碼
            5.直方圖         
            6.直方圖維度
            7.直方圖每個維度的尺寸數組   
            8.每一維數組的範圍    
            9.直方圖是否是均勻   
            10.配置階段不清零


C++

// VC_FANFUHAN_OPENCV017.cpp : 定義主控台應用程式的進入點。
//
/*
// Debug | x32
通用屬性
| C/C++
|	| 一般
|		| 其他 Include 目錄 -> C:\opencv\build\include
|
| 連結器
| 	|一一般
|		|  其他程式庫目錄 -> C:\opencv\build\x64\vc15\lib
|
| 	|一輸入
|		| 其他相依性 -> opencv_world411d.lib;%(AdditionalDependencies)
// Releas | x64
組態屬性
| C/C++
|	| 一般
|		| 其他 Include 目錄 -> C:\opencv\build\include
|
| 連結器
| 	|一般
|		| 其他程式庫目錄 -> C:\opencv\build\x64\vc15\lib
|
| 	|一輸入
|		| 其他相依性 -> opencv_world411.lib;%(AdditionalDependencies)
*/
#include "stdafx.h"
#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>

using namespace std;
using namespace cv;

void showHistogram(InputArray src, cv::String StrTitle);

void pause()
{
	printf("Press Enter key to continue...");
	fgetc(stdin);
}
int main()
{
	Mat src = imread("../../images/test.png");
	if (src.empty())
	{
		cout << "could not load image.." << endl;
		pause();
		return -1;
	}
	else
	{
		imshow("input", src);
		showHistogram(src,"Histogram");

		Mat src_gray;
		cvtColor(src, src_gray, COLOR_BGR2GRAY);
		imshow("input_gray", src_gray);
		showHistogram(src_gray,"Histogram_gray");

		waitKey(0);
	}

	return 0;
}
void showHistogram(InputArray src, cv::String StrTitle)
{
	bool blnGray = false;
	if (src.channels() == 1)
	{
		blnGray = true;
	}

	// 三通道/單通道 直方圖 紀錄陣列
	vector<Mat> bgr_plane;
	vector<Mat> gray_plane;

	// 定义参数变量
	const int channels[1] = { 0 };
	const int bins[1] = { 256 };
	float hranges[2] = { 0, 255 };
	const float *ranges[1] = { hranges };
	Mat b_hist, g_hist, r_hist,hist;
	// 计算三通道直方图
	if (blnGray)
	{
		split(src, gray_plane);
		calcHist(&gray_plane[0], 1, 0, Mat(), hist, 1, bins, ranges);
	}
	else
	{
		split(src, bgr_plane);
		calcHist(&bgr_plane[0], 1, 0, Mat(), b_hist, 1, bins, ranges);
		calcHist(&bgr_plane[1], 1, 0, Mat(), g_hist, 1, bins, ranges);
		calcHist(&bgr_plane[2], 1, 0, Mat(), r_hist, 1, bins, ranges);
	}

	/*
	* 显示直方图
	*/
	int hist_w = 512;
	int hist_h = 400;
	int bin_w = cvRound((double)hist_w / bins[0]);
	Mat histImage = Mat::zeros(hist_h, hist_w, CV_8UC3);
	// 归一化直方图数据
	if (blnGray)
	{
		normalize(hist, hist, 0, histImage.rows, NORM_MINMAX, -1);
	}
	else
	{
		normalize(b_hist, b_hist, 0, histImage.rows, NORM_MINMAX, -1);
		normalize(g_hist, g_hist, 0, histImage.rows, NORM_MINMAX, -1);
		normalize(r_hist, r_hist, 0, histImage.rows, NORM_MINMAX, -1);
	}

	// 绘制直方图曲线
	for (int i = 1; i < bins[0]; ++i)
	{
		if (blnGray)
		{
			line(histImage, Point(bin_w * (i - 1), hist_h - cvRound(hist.at<float>(i - 1))),
				Point(bin_w * (i), hist_h - cvRound(hist.at<float>(i))), Scalar(255, 255, 255),
				2, 8, 0);
		}
		else
		{
			line(histImage, Point(bin_w * (i - 1), hist_h - cvRound(b_hist.at<float>(i - 1))),
				Point(bin_w * (i), hist_h - cvRound(b_hist.at<float>(i))), Scalar(255, 0, 0),
				2, 8, 0);
			line(histImage, Point(bin_w * (i - 1), hist_h - cvRound(g_hist.at<float>(i - 1))),
				Point(bin_w * (i), hist_h - cvRound(g_hist.at<float>(i))), Scalar(0, 255, 0),
				2, 8, 0);
			line(histImage, Point(bin_w * (i - 1), hist_h - cvRound(r_hist.at<float>(i - 1))),
				Point(bin_w * (i), hist_h - cvRound(r_hist.at<float>(i))), Scalar(0, 0, 255),
				2, 8, 0);
		}


	}
	imshow(StrTitle, histImage);
}


Python

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt


def custom_hist(gray):
    h, w = gray.shape
    hist = np.zeros([256], dtype=np.int32)
    for row in range(h):
        for col in range(w):
            pv = gray[row, col]
            hist[pv] += 1

    y_pos = np.arange(0, 256, 1, dtype=np.int32)
    plt.bar(y_pos, hist, align='center', color='r', alpha=0.5)
    plt.xticks(y_pos, y_pos)
    plt.ylabel('Frequency')
    plt.title('Histogram')

    # plt.plot(hist, color='r')
    # plt.xlim([0, 256])
    plt.show()


def image_hist(image):
    cv.imshow("input", image)
    color = ('blue', 'green', 'red')
    for i, color in enumerate(color):
        hist = cv.calcHist([image], [i], None, [256], [0, 256])
        plt.plot(hist, color=color)
        plt.xlim([0, 256])
    plt.show()


src = cv.imread("../images/test.png")
cv.namedWindow("input", cv.WINDOW_AUTOSIZE)
gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
cv.imshow("input", gray)
#custom_hist(gray)
image_hist(src)
cv.waitKey(0)
cv.destroyAllWindows()


★結果圖:

★延伸說明/重點回顧:


One thought on “jashliao 用 VC++ 實現 fanfuhan OpenCV 教學017 ~ opencv-017-計算/顯示 彩色/灰階 對應的直方圖

發表迴響

你的電子郵件位址並不會被公開。 必要欄位標記為 *