1. 程式人生 > >學習OpenCV範例(十七)——直方圖計算和均衡化

學習OpenCV範例(十七)——直方圖計算和均衡化

本次案例將為大家介紹直方圖計算和直方圖均衡化,直方圖的計算非常有用,在很多場合下都可以用上,不僅僅是在影象的灰度值上,還可能是在影象的其他特徵上;影象的均衡化在影象預處理時經常被用到,它可以增強對比度,使得畫素強度分佈範圍更廣。

1、原理

直方圖計算:

直方圖均衡化:

學習OpenCV:

2、程式碼實現

程式功能:

①輸入一張圖片,分解影象的三個通道,對三個通道進行直方圖計算,並顯示出來

②分解影象的三個通道,對三個通道進行直方圖均衡,再合併三個通道,最後顯示影象和直方圖計算影象

#include "stdafx.h"

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>

using namespace std;
using namespace cv;

Mat calchistcontrol(vector<Mat> rgb);
void draw(Mat hist,int histSize,Mat histImage,int bin_w,int hist_h,int rgb);
/** @函式 main */
int main( int argc, char** argv )
{
	Mat src, dst,rgb_merge,histImage,histImage1;
	/// 裝載影象
	src = imread("scenery2.jpg" , 1 );
	imshow("source_image",src);

	if( !src.data )
	{ return -1; }

	/// 分割成3個單通道影象 ( R, G 和 B )
	vector<Mat> rgb_planes;
	split( src, rgb_planes );

	///直方圖計算
	histImage=calchistcontrol(rgb_planes);

	///三個通道直方圖均衡化
	vector<Mat> rgb_planes1;
	split(src,rgb_planes1);
	equalizeHist(rgb_planes1[0],rgb_planes1[0]);
	equalizeHist(rgb_planes1[1],rgb_planes1[1]);
	equalizeHist(rgb_planes1[2],rgb_planes1[2]);

	///三個通道直方圖均衡化後直方圖計算
	histImage1=calchistcontrol(rgb_planes1);

	///合併三通道
	merge(rgb_planes1,rgb_merge);

	/// 顯示直方圖
	imshow("calcHist Demo", histImage );
	imshow("calcHist Demo1",histImage1);
	imshow("rgb_merge",rgb_merge);

	waitKey(0);

	return 0;

}
Mat calchistcontrol(vector<Mat> rgb)
{

	vector<Mat> rgb_planes;
	rgb_planes=rgb;
	/// 設定bin數目
	int histSize = 255;

	/// 設定取值範圍 ( R,G,B) )
	float range[] = { 0, 255 } ;
	const float* histRange = { range };

	bool uniform = true; bool accumulate = false;

	Mat r_hist, g_hist, b_hist;

	/// 計算直方圖:
	calcHist( &rgb_planes[0], 1, 0, Mat(), r_hist, 1, &histSize, &histRange, uniform, accumulate );
	calcHist( &rgb_planes[1], 1, 0, Mat(), g_hist, 1, &histSize, &histRange, uniform, accumulate );
	calcHist( &rgb_planes[2], 1, 0, Mat(), b_hist, 1, &histSize, &histRange, uniform, accumulate );

	// 建立直方圖畫布
	int hist_w = 400; int hist_h = 400;
	int bin_w = cvRound( (double) hist_w/histSize );

	Mat histImage( hist_w, hist_h, CV_8UC3, Scalar( 0,0,0) );

	/// 將直方圖歸一化到範圍 [ 0, histImage.rows ]
	normalize(r_hist, r_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() );
	normalize(g_hist, g_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() );
	normalize(b_hist, b_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() );

	/// 在直方圖畫布上畫出直方圖
	draw(r_hist,histSize,histImage,bin_w,hist_h,1);
	draw(g_hist,histSize,histImage,bin_w,hist_h,2);
	draw(b_hist,histSize,histImage,bin_w,hist_h,3);
	return histImage;
}
void draw(Mat hist,int histSize,Mat histImage,int bin_w,int hist_h,int rgb)
{
	Scalar a;
    switch(rgb)
	{
	case 1: a=Scalar(0,0,255);break;
	case 2: a=Scalar(0,255,0);break;
	case 3: a=Scalar(255,0,0);break;
	}
	int flag=1,first;
		for( int i = 0; i < histSize; i++ )
	{  
		if (flag==1)
	{
		if (cvRound(hist.at<float>(i)!=0))
		{
			flag=2;
			first=i;
		}
		else
		{
			i++;
		}
	}
		else
		{
			if (cvRound(hist.at<float>(i)!=0))
			{
			line( histImage, Point( bin_w*(first), hist_h - cvRound(hist.at<float>(first)) ) ,
			      Point( bin_w*(i), hist_h - cvRound(hist.at<float>(i)) ),
			      a, 2, 8, 0  );
			first=i;
			}
			else
			{
				i++;
			}
		}

	}
}

3、執行結果


                                  圖1、源影象


                                      圖2、合併影象

  

        圖3、源影象直方圖                     圖4、合併影象直方圖

4、用到的類和函式

calcHist

功能:計算影象 的直方圖

結構:

 void calcHist(const Mat* arrays, int narrays, const int* channels, InputArray mask, OutputArray hist, int dims, const int* histSize, const float** ranges, bool uniform=true, bool accumulate=false )

arrays :源影象集,他們都需要有同樣的depth,CV_8U或者CV_32F,同樣的size,可以有任意的通道數
narrays :輸入影象的個數
channels :需要統計的通道 (dim)索引
mask :掩碼( 0 表示忽略該畫素), 如果未定義,則不使用掩碼,如果不為null,則只有與mask非零元素對應的畫素點會被包含在計算直方圖當中。
hist :輸出直方圖陣列,是一個 dims 維的陣列
dims :直方圖的維數
histSize :直方圖的大小,即每個維度的bin數目
ranges:每個維度的取值範圍
uniform 、accumulate: bin大小相同,清除直方圖痕跡

hist.at<float>(i)表示第i個bin中所儲存的統計數量

equalizeHist

功能:灰度圖象直方圖均衡化

結構:

 void equalizeHist(InputArray src, OutputArray dst)

src:源影象,8bit單通道圖片

dst:目標影象,和源影象有同樣的size和type

操作:

①、計算src的直方圖H

②、歸一化直方圖,使得H中bins的和為255;

③、計算直方圖積分

                               H'_i =  \sum _{0  \le j < i} H(j)

④、採用H'作為查詢表進行變換:\texttt{dst}(x,y) = H'(\texttt{src}(x,y))

該方法歸一化影象亮度和增強對比度。

相關推薦

學習OpenCV範例——直方圖計算均衡化

本次案例將為大家介紹直方圖計算和直方圖均衡化,直方圖的計算非常有用,在很多場合下都可以用上,不僅僅是在影象的灰度值上,還可能是在影象的其他特徵上;影象的均衡化在影象預處理時經常被用到,它可以增強對比度,使得畫素強度分佈範圍更廣。 1、原理 直方圖計算: 直方圖均衡化:

學習OpenCV範例——輪廓提取形狀描述符

本範例主要介紹瞭如何提取輪廓和用一些形狀描述符對輪廓進行表述,輪廓提取函式涉及到的引數很多,沒有經常用到它的話,對引數的瞭解就不會太深刻,這裡也按照本人搜尋出來的一些資料進行總結,希望對大家有用。 1、程式碼實現 本程式碼實現了多個功能 建立了三個滑動條: 第一個滑動條表示

學習OpenCV範例——影象的腐蝕與膨脹

這次範例相對比較簡單,是涉及到形態學操作的問題,原理也是比較簡單,學習起來比較輕鬆,大家看完這次的範例分析就可以明白到底影象的腐蝕和膨脹是怎麼回事了。 1、原理 簡單來講,形態學操作就是基於形狀的一系列影象處理操作。通過將 結構元素 作用於輸入影象來產生輸出影象。 最基本的

學習OpenCV範例——反向投影

本次要講的範例是反向投影,反向投影如果是按照字面上的理解,還有書本上的理解可能會比較困難,但是如果是舉一些具體的簡單的例子,那可能就比較容易接受了,應用的話,可以檢測出膚色區域,例如,你有一個膚色直方圖 ( Hue-Saturation 直方圖 ),你可以用它來尋找影象中的

學習OpenCV範例——sobel,laplace,canny的運用

本次範例將要學習關於邊緣提取,影象銳化的三個基本函式,風別是Sobel(),Laplacian(),Canny(),會從原理講起,再到程式碼實現,最後會貼出執行結果,進行三種結果的對比。 1、原理及計算 Sobel: 原理: 由上圖,你可以看到在 邊緣 ,相素值顯著的 改

學習OpenCV範例——霍夫變換

本次範例通過霍夫變換檢測直線和圓,講解霍夫線變換和霍夫圓變換的原理,程式碼實現,和演示結果,使用霍夫線變換之前, 首先要對影象進行邊緣檢測的處理,也即霍夫線變換的直接輸入只能是邊緣二值影象。而霍夫圓變換則只要輸入灰度影象即可,因為在霍夫圓變換的過程中已經用到了canny邊緣

opencv學習之XMLYAML檔案讀寫操作

可能大部分人到現在接觸的XML和YAML檔案很少,等以後訓練人臉模型進行人臉識別的時候用的就多了。現在先了解一下這兩種檔案型別。 XML:Extensible Markup Language,可擴充套件標記語言,標準通用語言的子集,是一種用於標記電子檔案使其具

Hadoop學習之路MapReduce框架Partitoner分區

div get() 劃分 mapreduce ride 作用 程序 輸出 lin Partitioner分區類的作用是什麽? 在進行MapReduce計算時,有時候需要把最終的輸出數據分到不同的文件中,比如按照省份劃分的話,需要把同一省份的數據放到一個文件中;按照性別劃分

Python學習之旅

Python基礎知識(16):面向物件程式設計(Ⅰ) 類和例項 類是抽象的模板 例項是根據類創建出來的一個個具體的物件,每個物件都擁有相同的方法,但各自的資料可能不同。 類可以在建立例項的時候,把一些我們認為必須繫結的屬性強制填寫進去 方法就是與例項繫結的函式,和普通函式不同,方法可以直接訪問例項的

【零基礎】Python3學習課後練習題

本文是跟著魚C論壇小甲魚零基礎學習Python3的視訊學習的,課後題也是跟隨每一課所附屬的題目來做的,根據自己的理解和標準答案記錄的筆記。 第十九課 測試題: 0.下邊程式會輸出什麼? def next():       print('我在next()函式裡.

Python小白學習之路—【內建函式二】

序列操作類函式 all() 功能:判斷可迭代物件的每個元素是否都為True值注意:If the iterable is empty, return True.(舉例3) 回顧:None     ''      ()     {}       []    0 ==>False其餘 ==>Tru

學習OpenCV範例二十三—GMM前景檢測

前一篇部落格中有談論到混合高斯模型GMM,但是隻是在上面的一個小應用,可能沒有很徹底的分析,大部分讀者看起來有點吃力,那麼在這篇微博中就給大家分析一下GMM在前景檢測的原理以及在OpenCV中的運用,當然長篇大論的原理我還是不全部寫出來的,依舊會貼出其他高手的部落格,他們寫

Linux 學習之路:RAIDLVM

傳輸速度 Mb/8=MB 硬碟的介面: IDE(ATA):133Mbps 並行匯流排 SATA:300Mbps,600Mbps,6Gbps 序列匯流排 USB:USB3.0:480Mbps 序列匯流排 SCSI:Small Computer System Int

opencv學習:影象金子塔

邊緣檢測運算元 參考學習連結:https://blog.csdn.net/xiaowei_cqu/article/details/7829481 影象金子塔 參考學習連結:https://www.cnblogs.com/Matrix420/p/4214123.html open

OpenCV學習筆記模板匹配

我的目的就是選取影象中的指示燈,識別那種功能的指示燈亮了,進而知道那種功能打開了。 模板匹配: 模板匹配是傻瓜似的識別,從一副影象中尋找與模板影象相似部分的技術。模板匹配由matchTemplate()函式完成。 介紹兩個函式,matchTemplate()和minMaxL

opencv學習筆記——線性濾波

影象線性濾波: 影象濾波:指儘量在儲存影象細節特徵的條件下對目標影象的噪聲進行抑制。 影象濾波的目的:一是抽出物件的特徵作為影象識別的特徵模式;二是消除影象中混入的噪聲。 影象濾波的要求:一是不能損壞影象的輪廓及邊緣等重要資訊;二是使影象清晰視覺效果好。 濾

學習OpenCV範例——Keypoints+Knn+findHomography進行目標定位

本範例的程式碼主要都是 學習OpenCV——通過KeyPoints進行目標定位這篇部落格提供的,然後在它的基礎上稍加修改,檢測keypoints點的檢測器是SURF,獲取描述子也是用到SURF來描述,而用到的匹配器是FlannBased,匹配的方式是Knn方式,最後通過f

iOS學習筆記——文件操作NSFileManager

技術分享 append hint pbo -cp fcm object 寫入 rtmp http://blog.csdn.net/xyz_lmn/article/details/8968213 iOS的沙盒機制,應用只能訪問自己應用目錄下的文件。ios不像Androi

python學習 擴展python

生成 實現 語言 擴展 運行速度 ava python學習 簡單 用c語言實現 c, c++, java比python快幾個數量級。 17.1 考慮哪個更重要 開發速度還是運行速度更重要。 17.2 非常簡單的途徑:Jython和IronPython Jython可以直接訪

Java學習筆記:super關鍵字

mage cnblogs 分享 關鍵字 super關鍵字 log .cn nbsp java Java學習筆記(十七):super關鍵字