冪次變換
冪次變換,點運算的一種,運算公式爲s=crγ,其中,c和γ是正常數。
當γ<1,此時擴展低灰度級,壓縮高灰度級,在正比函數上方,使圖像變亮;
當γ>1,此時擴展高灰度級,壓縮低灰度級,在正比函數下方,使圖像變暗。
核磁共振圖像
是利用核磁共振(nuclear magnetic resonance,簡稱NMR)原理,依據所釋放的能量在物質內部不同結構環境中不同的衰減,通過外加梯度磁場檢測所發射出的電磁波,即可得知構成這一物體原子核的位置和種類,據此可以繪製成物體內部的結構圖像。
本圖像來源翰·霍普金斯大學Elliot Fishman博士和Karen Horton博士的教學案例和圖片。圖像大小爲455*600,8位灰度圖像。爲了增強本次實驗效果,將此圖像人爲的進行了亮度調低。
亮度調低
代碼實現
平臺:vs2015
語言:C語言
流程:
1)讀取圖片
2)對每個像素進行冪次計算
3)輸出處理後的圖片
4)改變γ的值,重複上述流程
關鍵代碼:
for (i = 0; i < height; i++)
{
for (j = 0; j < width; j++)
{
temp = c * pow( Pic[i][j]/255.0 , v )*255;
Pic[i][j] = (char)temp;
}
}
處理結果:
分析:
如冪次變換特點——當γ<1,此時擴展低灰度級,壓縮高灰度級,使圖像變亮;當γ>1,此時擴展高灰度級,壓縮低灰度級,使圖像變暗。
感覺在γ爲0.4時相比於0.6的一些細節更清晰一些,當γ爲0.2時圖片有點過亮,一些細節反而不容易觀察。
而當γ大於1時,原本就比較暗的圖像變得更暗,基本上無法觀察了。
另外,還測試了γ分別爲0.1,0.2,0.3,0.4……0.9的結果,發現確實可以通過冪律變換實現亮暗度變化的對比度增強。
遇到問題
最初寫代碼直接帶入公式,代碼寫成了如下:
for (i = 0; i < height; i++)
{
for (j = 0; j < width; j++)
{
temp = c * pow( Pic[i][j] , v );
Pic[i][j] = (char)temp;
}
}
即直接按照公式s=crγ進行帶入計算。結果當γ=0.6時,得到的結果如下:
圖像反而變暗了,顯然這是不對的。看了一下那些曲線明白了這個公式的含義,修改爲:
for (i = 0; i < height; i++)
{
for (j = 0; j < width; j++)
{
temp = c * pow( Pic[i][j]/255 , v )*255;
Pic[i][j] = (char)temp;
}
}
這樣運行後反而成了一片黑了,也就是所有像素值爲0。發現忽略了Pic[i][j]/255並不是浮點運算,得到的結果必然爲0。於是將255改爲255.0,解決問題。
附代碼:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define height 600
#define width 455
typedef unsigned char BYTE; // 定義BYTE類型,佔1個字節
//s = cr v
int c = 1;
float v = 0.6;
float temp;
int main(void)
{
FILE *fp = NULL;
BYTE *ptr;
BYTE **Pic = new BYTE *[height];
for (int i = 0; i != height; ++i)
{
Pic[i] = new BYTE[width];
}
int i, j;
fp = fopen("untitled.raw", "rb");
ptr = (BYTE*)malloc(width * height * sizeof(BYTE));//創建內存
for (i = 0; i < height; i++)
{
for (j = 0; j < width; j++)
{
fread(ptr, 1, 1, fp);
Pic[i][j] = *ptr; // 把圖像輸入到2維數組中,變成矩陣型式
ptr++;
}
}
fclose(fp);
for (i = 0; i < height; i++)
{
for (j = 0; j < width; j++)
{
temp = c * pow( Pic[i][j]/255.0 , v )*255;
Pic[i][j] = (char)temp;
}
}
fp = fopen("output.raw", "wb");
for (i = 0; i < height; i++)
{
for (j = 0; j < width; j++)
{
fwrite(&Pic[i][j], 1, 1, fp);
}
}
fclose(fp);
return 0;
}