去掉圖片黑背景輸出爲透明背景

最近遇到了一個需求,是要去掉一張圖片的黑色背景,以下圖所示:html

image.png

若是使用OPENCV ,加上一些圖像處理的算法,是能夠實現去除任何背景的。可是因爲這個需求就是去掉黑色背景,感受不必用到哪些比較複雜的算法。前端

因而打算在網絡上搜索了一下,開始沒有搜搜到,卻是搜索到一篇用ps如何來去掉黑色背景的思路:
去掉圖片黑背景輸出爲透明png(算法和工具)程序員

可是裏面主要是說用PS的操做,並且裏面說的原理,也不是很清晰。
因此打算本身想一個算法。算法

錯誤的思路

最開始的想法是判斷顏色是不是黑色(r = 0,g = 0,b = 0),若是是黑色,就把該像素的透明度設置爲0。 可是結果確定是不如意的,以下圖所示:編程

image.png

結果是,沒有一個像素被設置爲全透明的。 爲何呢? 由於這個背景並非純黑色的,只是偏黑色,好比像素值(r=15,g=5,b=5),不是純黑色,可是人眼的感受是黑色的。canvas

正確的思路

通過思索,想到了另一種思路,就是越黑的顏色,其透明度設置的越低。 所以只須要去除像素中三個通道中的較大值,設置爲顏色的透明度便可,好比像素值(r=15,g=5,b=5),則能夠把透明度設置爲
Math.max(15,5,5) = 15。瀏覽器

下面是示例代碼:網絡

function removeBlackBackgroundFunc(frameImageData) {
   let data = frameImageData.data;
   for(var i = 0;i < data.length / 4; i ++){
      var index = i * 4;
      var r = data[index],g = data[index + 1],b = data[index + 2],a = data[index + 3];
      var max = Math.max(r,g,b);
      data[index + 3] = max;
      if(r == 0 && g == 0 && b == 0){
        data[index + 3] = 0;
      }
   }
   return frameImageData;
}

把去掉黑色背景的圖繪製到一個藍色的背景上面,代碼以下:架構

ctx.globalCompositeOperation = 'destination-over';
  ctx.fillStyle = 'rgba(0,0,255,1.0)';
  ctx.fillRect(0,image.height,image.width,image.height + 10);

最終以下圖所示:編程語言

image.png

原理總結

因爲我使用的是瀏覽器 JavaScript編程語言,因此我使用的是瀏覽器上面canvas的功能。
首先把圖片繪製到canvas上面,而後能夠經過canvas的相關方法取到每個像素,而後使用去黑底的方法 操縱像素。

若是讀者不清楚canvas相關知識點,建議學習相關知識,也推薦有興趣讀者,訂閱專欄:
Canvas高級進階 https://xiaozhuanlan.com/canvas,相關知識會在專欄中介紹。

去黑底的原理,用通俗的話來講 「越黑的像素越透明」。

不一樣的方法,實現的細節上有可能會有些許區別。
好比,咱們能夠考慮把像素的最大值取出後,把線性空間變換到非線性空間,好比以下代碼:

var adjust = 0.8;
 data[index + 3] = Math.pow(max/255,adjust) * 255;

最終的效果,會有細節上的些許差異,能夠調整adjust查看細節上的差別。

歡迎關注公衆號「ITman彪叔」。彪叔,擁有10多年開發經驗,現任公司系統架構師、技術總監、技術培訓師、職業規劃師。在計算機圖形學、WebGL、前端可視化方面有深刻研究。對程序員思惟能力訓練和培訓、程序員職業規劃有濃厚興趣。
ITman彪叔公衆號

相關文章
相關標籤/搜索