抖動法顯示灰階映像(Qt 實現)

來源:互聯網
上載者:User

標籤:qt   影像處理   

有時,我們要在只能顯示黑白兩種顏色的顯示裝置上顯示一副灰階映像。這時就要採用所謂的抖動法(Dithering)來類比出灰階效果來。
比如下面這幅圖:

如果只是做個簡單的二值化處理,得到的結果是這樣的(以 128 為閾值)

雖然還能看出這個映像的內容,但是效果並不好。

一種直觀的想法就是在做二值化時引入隨機數,對於所有值為 x 的像素,以 x/256 為機率將這些像素點點亮。下面的代碼就可以實現這個功能。

QImage RandomDithering(QImage &image){    int width = image.width();    int height = image.height();    QImage ret = image.copy();    for(int i = 0; i < height; i ++)    {        uchar * p = ret.scanLine(i);        for(int j = 0; j < width; j ++)        {            int x = rand() % 256;            p[j] = ( x <= p[j] ?  255 : 0 );        }    }    return ret;}

實際實驗一下,這樣做的效果並不太好。

原因嘛,就是引入了太多的雜訊。其實我們可以抖動的不這麼厲害。下面的代碼就可以控制抖動的大小。

QImage RandomDithering(QImage &image, int dither){    int width = image.width();    int height = image.height();    QImage ret = image.copy();    for(int i = 0; i < height; i ++)    {        uchar * p = ret.scanLine(i);        for(int j = 0; j < width; j ++)        {            int x = rand() % (2 * dither) - dither;            p[j] = (p[j] + x >= 128 ? 255 : 0);        }    }    return ret;}

這個代碼,當 dither 值為 128 時就和上面隨機抖動代碼的結果相同了。如果 dither 值為 0, 那就退化成了簡單的二值化。

當 dither = 50 時,是下面的效果:

dither = 10 時:

可以看出,通過調整 dither ,可以達到不錯的效果。

除了這種隨機抖動法,還有些確定性抖動處理方法,其中最常用的應該算是 Floyd–Steinberg dithering。

這種演算法的介紹可以參考: https://en.wikipedia.org/wiki/Floyd%E2%80%93Steinberg_dithering

下面我也給個我寫的一個實現。

QImage FloydSteinbergDithering(QImage &image){    int width = image.width();    int height = image.height();    QImage ret = image.copy();    for(int i = 0; i < height - 1; i ++)    {        uchar * p = ret.scanLine(i);        uchar *pNext = ret.scanLine(i + 1);        for(int j = 0; j < width - 1; j ++)        {            int diff;            if( p[j] > 128 )            {                diff = p[j] - 255;                p[j] = 255;            }            else            {                diff = p[j];                p[j] = 0;            }            pNext[j] = qBound(0, pNext[j] + diff * 3 / 16, 255);            p[j + 1] = qBound(0, p[j + 1] + diff * 3 / 16, 255);            pNext[j + 1] = qBound(0, pNext[j + 1] + diff * 1 / 4, 255);        }        p[width - 1] = (p[width - 1] >= 128 ? 255 : 0);    }    uchar * p = ret.scanLine(height - 1);    for(int j = 0; j < width; j ++)    {        p[j] = (p[j] >= 128 ? 255 : 0);    }    return ret;}

用這個演算法得到的映像是這樣的:

效果很不錯,這也是大家都喜歡用它的原因。

當然 Floyd–Steinberg dithering 的參數可以有不同的設定,得到的結果也不同。感興趣的同學可以自己做做實驗。

著作權聲明:本文為博主原創文章,未經博主允許不得轉載。

抖動法顯示灰階映像(Qt 實現)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.