2017年9月15日 星期五

技術筆記Dither

拍攝自當代館展場 很有Dither的感覺

這是玩具計劃延伸來與演算法有關筆記,原始連結

Dither及做法


This printer is not capable of printing anything but black or white pixels. The best way to give the illusion of grayscale is to “dither”. In image processing, dithering is a method of giving something the appearance of grayscale by alternating black and white.

Dither
熱感應噴頭,因為每個點只有1與0兩種選擇,沒有灰階的概念。直覺上就是用比較密的點表示黑,而比較稀鬆的點就是淺。(同樣技術可套用在EINK上)。要如何表示呢,這時讀過書就有用啦,誤差擴散演算法,能以學理的角度,看待和解決這個問題。

學理上來說,透過這個方式,可以降低圖像色彩的深度,顧名思義, 誤差擴散, 就是將色彩深度降低時, 將像素顏色的變化誤差, 擴散開去. 這使得肉眼在觀察圖片的時候, 相鄰的像素點集合整體 的誤差變小。

先以較多級度來當範例。256級灰度圖象上有一個點,灰度值是 120 (0~255),如果我們要將這張圖轉換成 16 級灰度,最簡單的方法是將每個像素點除以最簡單的方法是將每個像素點除以 16。那麼轉換后的值就是那麼轉換后的值就是 120/16=7.5。如果我們採取直接捨去,保留整數位后就是 7,誤差值0.5跑去哪裡了呢?

最簡單的誤差擴散方法是將這 0.5 的誤差放到這個點右邊/下邊的點上,我們可以按 3:2:3 的比例把它分配到右邊, 右下, 下邊的點上。即我們把右邊和下邊的點加上 (0.5*16)*3/8=3,把右下的點加上 (0.5*16)*2/8=2. 這樣處理完整個圖形,要比直接截尾的效果要好的多。實際上, 3:2:3 的誤差分配方案 並不算好。還可以試不同分法例如7:3:5:1

  X 7
3 5 1

更或者 42 分:

    X 8 4
2 4 8 4 2
1 2 4 2 1

如果每個點只有0或是1兩階怎麼辦呢?ch00ftech的範例認為小於128(256/2)的變成0,大於128的變成1,被捨棄的就依照模式分出去,有欠的,也依照同樣方式扣回來。(不論哪種方式,到邊界後都會忽略)

範例如下

             86     90    97
     82    90    102  117
     95    106  122  137

             0      126    97
     97    116  107  117
     95    106  122  137


             0      0      152
     97    131  146  125
     95    106  122  137

             0      0      255
     97    131  127   93
     95    106  122  137

參考1
參考2

其他技巧


原始影像,處理時,是每8X8進行處理。原因是原本專案使用F107,記憶體較小,且配合JPEG decoder,所以影像切割成8×8 pixel blocks進行處理。程式較複雜,邊界部分也有些誤差。在F429上應該都很容易解決。

  每個點的顏色經過GRAYSCALE變成256階的灰階R*210+G*720+B*70
  (因為整數系統,所以都放大成INT)
  The first step to getting a full color image through a black and white printer is to convert it to grayscale.
  每個PIXEL包含RGB顏色 標準方式是
    ditheredImage[i][j] = *(pSrcR++)*210 + *(pSrcG++)*720 + *(pSrcB++)*70;


  如果這個點,位置在邊界,要從上次的結果中,取得數值加回來
  然後對這64個點中各個項目進行dithering
     如果小於80000就是0,不然就是255000
     然後把多餘的數值,向右、右下、下、左下進行加總
  這就是上面的Dither動作

  最後將目前結果存入整體暫存區
      bmpBlock[(colcount/40)][319-by-((colcount%40)*8)]|=(1<<(7-bx));
  數字有點奇怪,必須要用張圖解釋



rescale
dest[dx,dy] = src[dx*src_width/dest_width,dy*src_height/dest_height]
初次實驗是  240(30) : 320  配合列印頭最大數據是 384(48) : 512
除了影像調整外,送到印表機時,因為那需要批次處理,也跟著做了改變

右邊是原始大小,中間和左邊已經放大

GAMMA亮度調整

Convolution
簡易又有效,連結位置

沒有留言:

張貼留言