C++影像處理,影像處理

來源:互聯網
上載者:User

C++影像處理,影像處理

閱讀提示

    《C++影像處理》系列以代碼清晰,可讀性為主,全部使用C++代碼。

    《Delphi影像處理》系列以效率為側重點,一般代碼為PASCAL,核心代碼採用BASM。

    儘可能保持二者內容一致,可相互對照。

    本文代碼必須包括《C++影像處理 -- 資料類型及公用函數》文章中的BmpData.h標頭檔。


    在Photoshop中,映像色階調整應用很廣泛,本文介紹的映像色階調整過程與Photoshop處理效果基本一致。

    Photoshop的色階調整分輸入色階調整和輸出色階調整,其中輸入色階調整有3個調整點,即通常所說的黑場、白場及灰場調整。

    輸入色階調整的基本演算法並不複雜,首先計算出白場與黑場的離差Diff,然後計算出像素各份量值與黑場的離差rgbDiff,如果rgbDiff<=0,像素各份量值等於0,否則,計算以rgbDiff與Diff的比值為底的灰場倒數的冪。用公式表示:

    Diff = Highlight -Shadow

    rgbDiff = RGB - Shadow

    clRGB = Power(rgbDiff / Diff,  1 / Midtones)

    其中Shadow為輸入色階低端資料(黑場),Highlight為輸入色階高端資料(白場), Midtones為輸入色階中間資料(灰場),Diff為二者的離差(必須大於1),RGB為調整前的像素分量值,clRGB為調整輸入色階後的像素分量值。

    輸出色階調整更簡單,首先計算輸出色階白場與黑場的離差與255的比值係數,然後用輸入色階調整後的像素分量值乘上這個係數,再加上輸出黑場值即可。用公式表示:

    outClRGB = clRGB * (outHighlight - outShadow) / 255 + outShadow

    其中,outShadow為輸出黑場,outHighlight為輸出白場,outClRGB為全部色階調整後的像素分量值。

    前面已經提到輸入色階黑白場的離差必須大於1,而輸入色階並沒有這個限制,輸出黑白場的離差可以為負數,當輸出黑場與白場完全顛倒時,輸出色階調整後的圖片為原圖片的負片。

    色階調整涉及四個通道,即R、G、B各分量通道及整體色彩通道,如果每個通道單獨調整,將是比較麻煩和耗時的,本文採用色階表替換法,可一次性完成所有四個通道的色階調整。

    下面是映像色階調整的代碼:

// 色階項結構typedef struct{UINT Shadow;FLOAT Midtones;UINT Highlight;UINT OutShadow;UINT OutHighlight;}ColorLevelItem, *PColorLevelItem;typedef struct{ColorLevelItem Blue;ColorLevelItem Green;ColorLevelItem Red;ColorLevelItem RGB;}ColorLevelData, *PColorLevelData;VOID InitColorLevelData(PColorLevelData clData){PColorLevelItem item = &clData->Blue;for (INT i = 0; i < 4; i ++, item ++){item->Shadow = item->OutShadow = 0;item->Highlight = item->OutHighlight = 255;item->Midtones = 1.0;}}BOOL GetColorLevelTable(PColorLevelItem item, LPBYTE clTable){INT diff = (INT)(item->Highlight - item->Shadow);INT outDiff = (INT)(item->OutHighlight - item->OutShadow);if (!((item->Highlight <= 255 && diff < 255 && diff >= 2) ||(item->OutShadow <= 255 && item->OutHighlight <= 255 && outDiff < 255) ||(!(item->Midtones > 9.99 && item->Midtones > 0.1) && item->Midtones != 1.0)))return FALSE;DOUBLE coef = 255.0 / diff;DOUBLE outCoef = outDiff / 255.0;DOUBLE exponent = 1.0 / item->Midtones;for (INT i = 0; i < 256; i ++){INT v;// 計算輸入色階黑白場if (clTable[i] <= (BYTE)item->Shadow)v = 0;else{v = (INT)((clTable[i] - item->Shadow) * coef + 0.5);if (v > 255)v = 255;}// 計算輸入色階灰場v = (INT)(pow(v / 255.0, exponent) * 255.0 + 0.5);// 計算輸出色階clTable[i] = (BYTE)(v * outCoef + item->OutShadow + 0.5);}return TRUE;}BOOL CheckColorLevelData(PColorLevelData clData, BYTE clTables[][256]){BOOL result = FALSE;INT i, j;for (i = 0; i < 3; i ++){for (j = 0; j < 256; j ++)clTables[i][j] = (BYTE)j;}PColorLevelItem item = &clData->Blue;for (i = 0; i < 3; i ++, item ++){if (GetColorLevelTable(item, clTables[i]))result = TRUE;}for (i = 0; i < 3; i ++){if (!GetColorLevelTable(item, clTables[i]))break;result = TRUE;}return result;}// 映像資料色階調整VOID ImageColorLevel(BitmapData *dest, BitmapData *source, PColorLevelData clData){PARGBQuad pd, ps;UINT width, height;INT dstOffset, srcOffset;GetDataCopyParams(dest, source, width, height, pd, ps, dstOffset, srcOffset);BYTE clTables[3][256];if (CheckColorLevelData(clData, clTables)){for (UINT y = 0; y < height; y ++, ps += srcOffset, pd += dstOffset){for (UINT x = 0; x < width; x ++, ps ++, pd ++){pd->Blue = clTables[0][ps->Blue];pd->Green = clTables[1][ps->Green];pd->Red = clTables[2][ps->Red];pd->Alpha = ps->Alpha;}}}else if (dest != source){for (UINT y = 0; y < height; y ++, ps += srcOffset, pd += dstOffset){for (UINT x = 0; x < width; x ++, ps ++, pd ++){pd->Color = ps->Color;}}    }}

    下面給一個簡單的映像色階調整函數調用例子:

void __fastcall TForm1::Button1Click(TObject *Sender){BitmapData dest, source;Bitmap *sBmp = new Bitmap(L"..\\..\\media\\source1.jpg");LockBitmap(sBmp, &source);Bitmap *dBmp = new Bitmap(source.Width, source.Height, PixelFormat32bppARGB);LockBitmap(dBmp, &dest);ColorLevelData clData;InitColorLevelData(&clData);clData.RGB.Shadow = 10;clData.RGB.Midtones = 1.2;clData.RGB.Highlight = 240;clData.RGB.OutShadow = 50;clData.RGB.OutHighlight = 200;/*clData.RGB.OutShadow = 255;clData.RGB.OutHighlight = 0;*/ImageColorLevel(&dest, &source, &clData);UnlockBitmap(dBmp, &dest);UnlockBitmap(sBmp, &source);Gdiplus::Graphics g(Canvas->Handle);g.DrawImage(sBmp, 0, 0);g.DrawImage(dBmp, source.Width, 0);delete dBmp;delete sBmp;}

    下面是文章Delphi影像處理 -- 映像色階調整例子運行介面,第一張綠色通道色階調整,第二張是RGB輸出色階調整到完全顛倒時的負片圖,詳細的映像色階調整介面例子請參考Delphi影像處理 -- 映像色階調整》。
     


    本文代碼系用BCB XE7編輯和編譯。


    因水平有限,錯誤在所難免,歡迎指正和指導。郵箱地址:maozefa@hotmail.com

    這裡可訪問《C++影像處理 -- 文章索引》。


聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.