導航:首頁 > 源碼編譯 > 直方圖均衡化源碼實現

直方圖均衡化源碼實現

發布時間:2023-02-26 07:18:55

A. OpenCV C++(四)----對比度增強

對比度增強或者稱為對比度拉伸就是圖像增強技術的一種,它主要解決由於圖像的灰度級范圍較小造成的對比度較低的問題,目的就是將輸出圖像的灰度級放大到指定的程度,使得圖像中的細節看起來更加清晰。對比 度增強有幾種常用的方法,如線性變換、分段線性變換、伽馬變換、直方圖正規化、直方圖均衡化、局部自適應直方圖均衡化等。

灰度直方圖是圖像灰度級的函數, 用來描述每個灰度級在圖像矩陣中的像素個數或者佔有率(概率)。

OpenCV提供了函數 calcHist 來實現直方圖的構建,但是在計算8點陣圖的灰度直方圖 時,它使用起來略顯復雜。下面是OpenCV源碼

可以定義函數 calcGrayHist 來計算灰度直方圖,其中輸入參數為8點陣圖,將返回的灰度直方圖存儲為一個1行256列的 Mat 類型。

圖像對比度是通過灰度級范圍來度量的,而灰度級范圍可通過觀察灰度直方圖得到,灰度級范圍越大代表對比度越高;反之,對比度越低,低對比度的圖像在視覺上給人的感覺是看起來不夠清晰,所以通過演算法調整圖像的灰度值,從而調整圖像的對比度是有必要的。最簡單的一種對比度增強方法是通過灰度值的線性變換來實現的。

當a=1,b=0時,O為I的一個副本;如果a>1,則輸出圖像O的對 比度比I 有所增大;如果0<a< 1,則O的對比度比I有所減小。而b值的改變,影響的是輸出圖像的亮度,當b> 0時,亮度增加;當b<0時,亮度減小。

在OpenCV中實現一個常數與矩陣相乘有多種方式。
1、convertTo

註:當輸出矩陣的數據類型是 CV_8U 時, 大於255的值會自動截斷為255

2、矩陣乘法運算

使用乘法運算符「*」, 無論常數是什麼數據類型, 輸出矩陣的數據類型總是和輸入矩陣的數據類型相同,當數據類型是 CV_8U 時,在返回值中將大於255的值自動截斷為255。

3、convertScaleAbs

直方圖正規化是一種自動選取a和b的值的線性變換方法。

利用 minMaxLoc 函數不僅可以計算出矩陣中的最大值和最小值, 而且可以求出最大 值的位置和最小值的位置。 當然,
在使用過程中如果只想得到最大值和最小值, 則將其 他的變數值設為 NULL 即可。

OpenCV提供的函數: normalize()
使用函數 normalize 對圖像進行對比度增強時, 經常令參數 norm_type=NORM_MINMAX , 和直方圖正規化原理詳解中提到的計算方法是相同的, 參數 alpha 相當於 Omax , 參數 beta 相當於 Omin 。 注意, 使用 normalize 可以處理多通道矩陣, 分別對每一個通道進行正規化操作。

非線性變換

假設輸入圖像為I,寬為W、 高為H,首先將其灰度值歸一化到[0,1]范圍,對於8位 圖來說,除以255即可。 I (r, c) 代表歸一化後的第r行第c列的灰度值, 輸出圖像記為 O, 伽馬變換就是令 O(r, c) =I(r, c) γ , 0≤r<H, 0≤c< W,

當γ=1時, 圖像不變。 如果圖像整體或者感興趣區域較暗, 則令0< γ< 1可以 增加圖像對比度; 相反, 如果圖像整體或者感興趣區域較亮, 則令γ>1可以降低圖像對比度。

伽馬變換在提升對比度上有比較好的效果, 但是需要手動調節γ值。

全局直方圖均衡化操作是對圖像I進行改變, 使得輸出圖像O的灰度直方圖 hist O 是「平」的, 即每一個灰度級的像素點個數是「相等」的。 注意,其實這里的「相等」不是嚴格意義上的等於, 而是約等於,

上述分別為I和O的累加直方圖

總結,對於直方圖均衡化的實現主要分四個步驟:

OpenCV實現的直方圖均衡化函數 equalize-Hist , 其使用方法很簡單, 只支持對 8點陣圖 的處理。

雖然全局直方圖均衡化方法對提高對比度很有效,但是均衡化處理以後暗區域的雜訊可能會被放大,變得清晰可 見,而亮區域可能會損失信息。為了解決該問題, 提出了自適應直方圖均衡化(Aptive Histogram Equalization) 方法。

自適應直方圖均衡化首先將圖像劃分為不重疊的區域塊(tiles) ,然後對每一個塊分別進行直方圖均衡化。 顯然, 在沒有雜訊影響的情況下, 每一個小區域的灰度直方圖會被限制在一個小的灰度級范圍內; 但是如果有雜訊, 每一個分割的區域塊執行直方圖均衡化後, 雜訊會被放大。為了避免出現雜訊這種情況, 提出了「限制對比度」(Contrast Limiting) [3],如果直方圖的bin超過了提前預設好的「限制對比度」, 那麼會被裁減, 然 後將裁剪的部分均勻分布到其他的bin, 這樣就重構了直方圖。

OpenCV提供的函數 createCLAHE 構建指向 CLAHE 對象的指針, 其中默認設置「限制 對比度」為40,塊的大小為8×8。

B. photoshop 怎麼實現直方圖均衡化

圖形處理中有一種對比度變換,像顯示器就有對比度調節,PhotoShop也有圖片的對比度修改,對比度的提高可以使圖像細節清晰,相反,對比度的減小可以隱藏圖像的細節,在一定程度上使圖像柔和。

對比度變換其中一種比較簡單的方法是直方圖均衡化。
所謂直方圖就是在某一灰度級的象素個數占整幅圖像的象素比 h=nj/N,其中nj是灰度級在j的象素數,N是總象素數,掃描整幅圖像得出的h的離散序列就是圖像的直方圖,h求和必然=1,所以直方圖可以看成是象素對於灰度的概率分布函數。

直方圖是高低不齊的,因為象素灰度是隨機變化的,直方圖均衡化就是用一定的演算法使直方圖大致平和。

演算法如下:
對於一個直方圖
設 Pr(r)是原始圖像直方圖,Ps(s)是均衡化的直方圖,
由於其是一個概率分布函數
所以有 Ps(s)ds=Pr(r)dr (編輯關系,ds,dr是積分變數)
因為要進行均衡化,令 Ps(s)=1,
得 ds=Pr(r)dr/1
兩邊積分得 s=F Pr(r)dr (因為編輯關系,左邊F表示積分符號....-__-++)
數字圖像是離散的,因此離散化上式得
sk=E{j=0,k}(nj/N) 左式k,j是離散量下標,因為編輯關系,E{0,k}表示下標0到k的連加符號,N是象素總數
由此得出每一象素的sk為均衡化後的正規化灰度(即灰度正規化到[0,1]),統計sk即可得出均衡化後的直方圖。
在均衡化過程中可以對每一象素映射到新的實際灰度值sk*255,就實現了圖像的變換
(嚴格理論中應該是灰度正規化到[0,1]區間,然後均衡化後的sk還要量化到原始的正規灰度以實現灰度合並,下面的BCB程序並沒有量化,而且255是固定灰度級,因為256色BMP的彩色表就是256個表項)

現在開始實踐
用BCB對一BMP灰度圖像進行直方圖均衡化處理,代碼如下
//----------------------------BCB6代碼

#include <vcl.h>
#pragma hdrstop
#include<stdio.h>
#include "Unit1.h"
#include"File1.h"

#pragma pack(1)

//BMP文件頭
struct BITMAPFILEHEADER_
{
short type;
int bfSize;
short re1,re2;
int Offbits;
};
//BMP信息頭
struct BITMAPINFO_
{
long size;
long width,height;
short planes,bitCount;
long comp,sizeImg;
long xpels,ypels;
long used,important;
};
//BMP彩色表項
struct COLOR_
{
char blue,green,red,re;
};
//------將BMP彩色表的數據校正到BCB TColor的數據。
void SwitchColor(long &c)
{
long blue=c& 0x000000ff;
long green=c& 0x0000ff00;
long red=c& 0x00ff0000;
c=(blue<<16) | green | (red>>16);
}

void xxx()
{
FILE *f=fopen("f:\\bbs_prev2.bmp","rb");
if(f==NULL) /*判斷文件是否打開成功*/
{
ShowMessage("File open error");
return;
}

fseek(f,0,0);//移動到開頭

//----------讀BMP文件頭
BITMAPFILEHEADER_ *bmph=new BITMAPFILEHEADER_();
if(fread((char*)bmph,sizeof(BITMAPFILEHEADER_),1,f)==NULL)
{
ShowMessage("File read error");
return;
}

//-----------讀BMP信息頭
BITMAPINFO_ *bmpi=new BITMAPINFO_();
if(fread((char*)bmpi,sizeof(BITMAPINFO_),1,f)==NULL)
{
ShowMessage("File read error2");
return;
}

//--------------讀彩色表
long *c=new long[bmph->Offbits-sizeof(BITMAPFILEHEADER_)-sizeof(BITMAPINFO_)];
fread((char*)c,bmph->Offbits-sizeof(BITMAPFILEHEADER_)-sizeof(BITMAPINFO_),1,f);

//----------顯示一些信息
Form1->Edit1->Text=IntToStr(bmph->bfSize);
Form1->Edit2->Text=IntToStr(bmpi->width);
Form1->Edit3->Text=IntToStr(bmpi->height);
Form1->Edit4->Text=IntToStr(bmpi->comp);
Form1->Edit5->Text=IntToStr(bmpi->used);

int i,j,k,wc;
long N=bmph->bfSize- bmph->Offbits;//象素總數
unsigned char *image=new char[N]; //點陣圖矩陣
unsigned char *newimage=new char[N];//變換後的點陣圖矩陣

fread(image,N,1,f);//讀入點陣圖矩陣

//---------直方圖數列初始化
//---------直方圖數列用來存儲正規化後的灰度
double *h=new double[255];//255個灰度級,保存原始圖像正規化灰度直方圖數據
for(i=0;i<255;i++)
h[i]=0.0;
double *nh=new double[255];//255個灰度級,保存變換後的圖像正規化灰度直方圖
for(i=0;i<255;i++)
nh[i]=0.0;

long *count=new long[255]; //每一灰度級的象素數量統計
for(i=0;i<255;i++)
count[i]=0;
for(i=0;i<N;i++)
{
count[image[i]]++;
}
//-----正規化灰度概率統計
for(i=0;i<255;i++)
{
h[i]=count[i]/(double)N;
}
//------正規化新灰度圖
double hc;
for(i=0;i<N;i++)
{
hc=0;
for(j=0;j<image[i];j++)
hc+=h[j];
nh[image[i]]+=hc; //保存新正規化灰度圖
newimage[i]=hc*255; //保存新圖像灰度索引
}
//----------顯示直方圖
for(i=0;i<255;i++)
{
//原始直方圖
Form1->Canvas->MoveTo(10+i,200);
Form1->Canvas->LineTo(10+i,200+h[i]*N);
//新直方圖
Form1->Canvas->MoveTo(300+i,200);
Form1->Canvas->LineTo(300+i,200+nh[i]*255);
}
//------顯示圖形
TColor *tc;
if(bmpi->width%4==0)//-----------因為BMP圖像4位元組對齊
wc=bmpi->width/4*4;
else
wc=(bmpi->width/4+1)*4;

long a;
long pos=0;
for( i=0;i<bmpi->height;i++)
{
for(j=0;j<wc;j++)
{
//-----原始圖形
a= c[image[pos]];
SwitchColor(a);
Form1->Canvas->Pixels[10+j][600-i]=a;
//------新圖形
a= c[newimage[pos]];
SwitchColor(a);
Form1->Canvas->Pixels[300+j][600-i]=a;
pos++;
}
}
fclose(f);
}

這個程序使用256色BMP文件,但程序代碼是針對灰度圖像的,用於彩色圖像時得出一些古怪色彩配合而已。

在對灰度圖像均衡化時
如果原始圖像對比度本來就很高,如果再均衡化則灰度調和,對比度降低。
在泛白緩和的圖像中,由於均衡化過程中會合並一些象素灰度,則會增大對比度,這里255灰度級太多,合並不明顯。
http://hi..com/j_fo/blog/item/09a6adc3f8078855b319a8ac.html
還有詳細的說明和圖解

C. 數字圖像處理Python實現圖像灰度變換、直方圖均衡、均值濾波

import CV2

import

import numpy as np

import random

使用的是pycharm

因為最近看了《銀翼殺手2049》,裡面Joi實在是太好看了所以原圖像就用Joi了

要求是灰度圖像,所以第一步先把圖像轉化成灰度圖像

# 讀入原始圖像

img = CV2.imread('joi.jpg')

# 灰度化處理

gray = CV2.cvtColor(img, CV2.COLOR_BGR2GRAY)

CV2.imwrite('img.png', gray)

第一個任務是利用分段函數增強灰度對比,我自己隨便寫了個函數大致是這樣的

def chng(a):

if a < 255/3:

b = a/2

elif a < 255/3*2:

b = (a-255/3)*2 + 255/6

else:

b = (a-255/3*2)/2 + 255/6 +255/3*2

return b

rows = img.shape[0]

cols = img.shape[1]

cover = .deep(gray)

for i in range(rows):

for j in range(cols):

cover[i][j] = chng(cover[i][j])

CV2.imwrite('cover.png', cover)

下一步是直方圖均衡化

# histogram equalization

def hist_equal(img, z_max=255):

H, W = img.shape

# S is the total of pixels

S = H * W * 1.

out = img.()

sum_h = 0.

for i in range(1, 255):

ind = np.where(img == i)

sum_h += len(img[ind])

z_prime = z_max / S * sum_h

out[ind] = z_prime

out = out.astype(np.uint8)

return out

covereq = hist_equal(cover)

CV2.imwrite('covereq.png', covereq)

在實現濾波之前先添加高斯雜訊和椒鹽雜訊(代碼來源於網路)

不知道這個椒鹽雜訊的名字是誰起的感覺隔壁小孩都饞哭了

用到了random.gauss()

percentage是雜訊佔比

def GaussianNoise(src,means,sigma,percetage):

NoiseImg=src

NoiseNum=int(percetage*src.shape[0]*src.shape[1])

for i in range(NoiseNum):

randX=random.randint(0,src.shape[0]-1)

randY=random.randint(0,src.shape[1]-1)

NoiseImg[randX, randY]=NoiseImg[randX,randY]+random.gauss(means,sigma)

if NoiseImg[randX, randY]< 0:

NoiseImg[randX, randY]=0

elif NoiseImg[randX, randY]>255:

NoiseImg[randX, randY]=255

return NoiseImg

def PepperandSalt(src,percetage):

NoiseImg=src

NoiseNum=int(percetage*src.shape[0]*src.shape[1])

for i in range(NoiseNum):

randX=random.randint(0,src.shape[0]-1)

randY=random.randint(0,src.shape[1]-1)

if random.randint(0,1)<=0.5:

NoiseImg[randX,randY]=0

else:

NoiseImg[randX,randY]=255

return NoiseImg

covereqg = GaussianNoise(covereq, 2, 4, 0.8)

CV2.imwrite('covereqg.png', covereqg)

covereqps = PepperandSalt(covereq, 0.05)

CV2.imwrite('covereqps.png', covereqps)

下面開始均值濾波和中值濾波了

就以n x n為例,均值濾波就是用這n x n個像素點灰度值的平均值代替中心點,而中值就是中位數代替中心點,邊界點周圍補0;前兩個函數的作用是算出這個點的灰度值,後兩個是對整張圖片進行

#均值濾波模板

def mean_filter(x, y, step, img):

sum_s = 0

for k in range(x-int(step/2), x+int(step/2)+1):

for m in range(y-int(step/2), y+int(step/2)+1):

if k-int(step/2) 0 or k+int(step/2)+1 > img.shape[0]

or m-int(step/2) 0 or m+int(step/2)+1 > img.shape[1]:

sum_s += 0

else:

sum_s += img[k][m] / (step*step)

return sum_s

#中值濾波模板

def median_filter(x, y, step, img):

sum_s=[]

for k in range(x-int(step/2), x+int(step/2)+1):

for m in range(y-int(step/2), y+int(step/2)+1):

if k-int(step/2) 0 or k+int(step/2)+1 > img.shape[0]

or m-int(step/2) 0 or m+int(step/2)+1 > img.shape[1]:

sum_s.append(0)

else:

sum_s.append(img[k][m])

sum_s.sort()

return sum_s[(int(step*step/2)+1)]

def median_filter_go(img, n):

img1 = .deep(img)

for i in range(img.shape[0]):

for j in range(img.shape[1]):

img1[i][j] = median_filter(i, j, n, img)

return img1

def mean_filter_go(img, n):

img1 = .deep(img)

for i in range(img.shape[0]):

for j in range(img.shape[1]):

img1[i][j] = mean_filter(i, j, n, img)

return img1

完整main代碼如下:

if __name__ == "__main__":

# 讀入原始圖像

img = CV2.imread('joi.jpg')

# 灰度化處理

gray = CV2.cvtColor(img, CV2.COLOR_BGR2GRAY)

CV2.imwrite('img.png', gray)

rows = img.shape[0]

cols = img.shape[1]

cover = .deep(gray)

for i in range(rows):

for j in range(cols):

cover[i][j] = chng(cover[i][j])

CV2.imwrite('cover.png', cover)

covereq = hist_equal(cover)

CV2.imwrite('covereq.png', covereq)

covereqg = GaussianNoise(covereq, 2, 4, 0.8)

CV2.imwrite('covereqg.png', covereqg)

covereqps = PepperandSalt(covereq, 0.05)

CV2.imwrite('covereqps.png', covereqps)

meanimg3 = mean_filter_go(covereqps, 3)

CV2.imwrite('medimg3.png', meanimg3)

meanimg5 = mean_filter_go(covereqps, 5)

CV2.imwrite('meanimg5.png', meanimg5)

meanimg7 = mean_filter_go(covereqps, 7)

CV2.imwrite('meanimg7.png', meanimg7)

medimg3 = median_filter_go(covereqg, 3)

CV2.imwrite('medimg3.png', medimg3)

medimg5 = median_filter_go(covereqg, 5)

CV2.imwrite('medimg5.png', medimg5)

medimg7 = median_filter_go(covereqg, 7)

CV2.imwrite('medimg7.png', medimg7)

medimg4 = median_filter_go(covereqps, 7)

CV2.imwrite('medimg4.png', medimg4)

閱讀全文

與直方圖均衡化源碼實現相關的資料

熱點內容
mac下python在哪 瀏覽:634
廣東惠州DNS伺服器地址 瀏覽:355
編譯影片時軟體渲染錯誤 瀏覽:623
流星蝴蝶劍解壓失敗 瀏覽:292
如何確認方舟編譯器 瀏覽:664
奶粉源箱源碼什麼意思 瀏覽:178
台州程序員兼職一般去哪些網站 瀏覽:388
舊版本怎麼下載到新的安卓 瀏覽:966
flash個人網站源碼下載 瀏覽:723
javasocketbyte 瀏覽:264
素描基礎教程pdf 瀏覽:541
香港商報pdf版 瀏覽:427
安卓手機怎麼錄制吉他彈奏 瀏覽:382
ie文件夾緩存在哪裡 瀏覽:265
圍棋排名演算法 瀏覽:963
zigbee加密演算法 瀏覽:464
柏楊版資治通鑒pdf 瀏覽:395
事業編程序員下班時間 瀏覽:10
linux中命令大全 瀏覽:40
pic單片機學習網站 瀏覽:165