最近遇到了一個需求,是要去掉一張圖片的黑色背景,以下圖所示:html
若是使用OPENCV ,加上一些圖像處理的算法,是能夠實現去除任何背景的。可是因爲這個需求就是去掉黑色背景,感受不必用到哪些比較複雜的算法。前端
因而打算在網絡上搜索了一下,開始沒有搜搜到,卻是搜索到一篇用ps如何來去掉黑色背景的思路:
去掉圖片黑背景輸出爲透明png(算法和工具)程序員
可是裏面主要是說用PS的操做,並且裏面說的原理,也不是很清晰。
因此打算本身想一個算法。算法
最開始的想法是判斷顏色是不是黑色(r = 0,g = 0,b = 0),若是是黑色,就把該像素的透明度設置爲0。 可是結果確定是不如意的,以下圖所示:編程
結果是,沒有一個像素被設置爲全透明的。 爲何呢? 由於這個背景並非純黑色的,只是偏黑色,好比像素值(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);
最終以下圖所示:編程語言
因爲我使用的是瀏覽器 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、前端可視化方面有深刻研究。對程序員思惟能力訓練和培訓、程序員職業規劃有濃厚興趣。