亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 開發 > HTML5 > 正文

html5利用canvas實現顏色容差摳圖功能

2024-09-05 07:23:11
字體:
來源:轉載
供稿:網友

利用canvas的getImageData,我們可以獲取到一張圖片每一個像素的信息,而通過對每一個像素信息的對比,我們就可以找到需要消去的像素點。比如下面這一張圖片,如果我們想要扣去白色部分(粉色是body的背景顏色)。

 

let canvas = document.querySelector('#canvas');let context = canvas.getContext('2d');let img = document.createElement('img');img.src = './head2.png';img.onload = function () {    canvas.height = img.height;    canvas.width = img.width;    context.drawImage(img, 0, 0);    cutout(canvas, [255, 255, 255], 0.2); // 對白色進行摳除,容差為0.2}function cutout(canvas, color, range = 0) {    let context = canvas.getContext('2d');    let imageInfo = context.getImageData(0, 0, canvas.width, canvas.height);    // pixiArr是一個數組,每四個數組元素代表一個像素點,這四個數組元素分別對應一個像素的r,g,b,a值。    let pixiArr = imageInfo.data;    for (let i = 0; i < pixiArr.length; i += 4) {    // 匹配到目標像素就將目標像素的alpha設為0        if (testColor([pixiArr[i], pixiArr[i + 1], pixiArr[i + 2]], color, range)) pixiArr[i + 3] = 0;    }    context.putImageData(imageInfo, 0, 0);}function testColor(current, target, range) {    for (let i = 0; i < 3; i++) {        if (!((1 - range) * target[i] <= current[i] && (1 + range) * target[i] >= current[i])) return false;    }    return true;}

 

testColor(current, target, range) 方法三個參數分別為 待檢測像素點的rgb數組 、 目標像素點的rgb數組 和 容差范圍 ,這里的容差只是簡單用r、g、b的值分別乘以(1 + range)和(1 - range)來計算并對比,不同的容差參數會得到不同的效果↓

range = 0.095

 

range = 0.1

 

range = 0.2

 

當然對于底色是標準的純色的圖片就不需要容差了。

邊界處理

但是有時候我們希望有一個邊界,讓摳圖操作不對邊界內部的像素造成影響。比如上面的圖片,我們希望不會對人物頭像內部的像素造成影響。 如果我們一行一行來看,是不是只要在碰到不是邊界像素的時候停止操作,就可以達到效果了呢?

我們對每一行分別進行掃描,定義一個左指針 left 指向這一行的第一個像素,定義一個右指針 right 指向這一行的最后一個像素,并用一個 leftF 標識左邊是否碰到邊界,一個 rightF 標識右邊是否碰到邊界,當沒碰到邊界時指針就一直向內收縮,直到兩個指針都碰到邊界或者左右指針重合就跳到下一行,直到所有行都掃描完畢。

function cutout(canvas, color, range = 0) {    let context = canvas.getContext('2d');    let imageInfo = context.getImageData(0, 0, canvas.width, canvas.height);    let pixiArr = imageInfo.data;    for (let row = 0; row < canvas.height; row++) {        let left = row * 4 * canvas.width; // 指向行首像素        let right = left + 4 * canvas.width - 1 - 3; // 指向行尾像素        let leftF = false; // 左指針是否碰到邊界的標識        let rightF = false; // 右指針是否碰到邊界的標識        while (!leftF || !rightF) { // 當左右指針都為true,即都碰到邊界時結束            if (!leftF) {                if (testColor([pixiArr[left], pixiArr[left + 1], pixiArr[left + 2]], color, range)) {                    pixiArr[left + 3] = 0; // 此像素的alpha設為0                    left += 4; // 移到下一個像素                } else leftF = true; // 碰到邊界            }            if (!rightF) {                if (testColor([pixiArr[right], pixiArr[right + 1], pixiArr[right + 2]], color, range)) {                    pixiArr[right + 3] = 0;                    right -= 4;                } else rightF = true;            }            if (left == right) { // 左右指針重合                leftF = true;                rightF = true;            };        }    }    context.putImageData(imageInfo, 0, 0);}

 

雖然大概完成了我們的需求,但是看一下上面頭發那為啥會多了一塊白色

 

因為我們僅僅只進行了行掃描,當左指針碰到頭發時就會停止掃描,但是頭發弧度里面的就無法被掃描到了,我們還需要進行列掃描,改造一下上面的方法:

function cutout(canvas, color, range = 0) {    let context = canvas.getContext('2d');    let imageInfo = context.getImageData(0, 0, canvas.width, canvas.height);    let pixiArr = imageInfo.data;    for (let row = 0; row < canvas.height; row++) {        let left = row * 4 * canvas.width;        let right = left + 4 * canvas.width - 1 - 3;        let leftF = false;        let rightF = false;        while (!leftF || !rightF) {            if (!leftF) {                if (testColor([pixiArr[left], pixiArr[left + 1], pixiArr[left + 2]], color, range)) {                    pixiArr[left + 3] = 0;                    left += 4;                } else leftF = true;            }            if (!rightF) {                if (testColor([pixiArr[right], pixiArr[right + 1], pixiArr[right + 2]], color, range)) {                    pixiArr[right + 3] = 0;                    right -= 4;                } else rightF = true;            }            if (left == right) {                leftF = true;                rightF = true;            };        }    }    // 同理進行列掃描    for (let col = 0; col < canvas.width; col++) {        let top = col * 4; // 指向列頭        let bottom = top + (canvas.height - 2) * canvas.width * 4 + canvas.width * 4; // 指向列尾        let topF = false;        let bottomF = false;        while (!topF || !bottomF) {            if (!topF) {                if (testColor([pixiArr[top], pixiArr[top + 1], pixiArr[top + 2]], color, range)) {                    pixiArr[top + 3] = 0;                    top += canvas.width * 4;                } else topF = true;            }            if (!bottomF) {                if (testColor([pixiArr[bottom], pixiArr[bottom + 1], pixiArr[bottom + 2]], color, range)) {                    pixiArr[bottom + 3] = 0;                    bottom -= canvas.width * 4;                } else bottomF = true;            }            if (top == bottom) {                topF = true;                bottomF = true;            };        }    }    context.putImageData(imageInfo, 0, 0);}

 

至于top和bottom為啥是那樣計算畫個矩陣圖大概就知道了。

 

處理后↓

 

其實還可以先將 pixiArr 包裝為以一個像素點為單位的矩陣

[    [{r: 255, g: 255, b: 255, a: 1}, {r: 255, g: 255, b: 255, a: 1}, {r: 255, g: 255, b: 255, a: 1}],    [{r: 255, g: 255, b: 255, a: 1}, {r: 255, g: 255, b: 255, a: 1}, {r: 255, g: 255, b: 255, a: 1}]    [{r: 255, g: 255, b: 255, a: 1}, {r: 255, g: 255, b: 255, a: 1}, {r: 255, g: 255, b: 255, a: 1}]]

處理后計算像素下標也就會更簡單,列掃描時直接先將這個矩陣旋轉,再用行掃描處理一遍就行了。這樣處理pixiArr也有利于進一步對算法進行優化。

上述方法雖然大概完成了摳圖效果,但是這種簡單處理還會有許多情況沒有考慮到。

比如右邊頭發這里是行掃描和列掃描都無法觸碰到的區域↓

 

下面的衣服也因為顏色和底色一樣且沒有邊界在列掃描中被直接抹去了↓

 

最后

對于主體和底色區分度很大的圖片來說,最開始的那種方法就已經夠用了。這篇中我采用的容差和邊界處理算法的優化空間還很大,但是它們是非常容易實現與理解的,這篇權當做一個引子,各位完全可以根據自己的能力繼續去實現邊界與容差算法。

總結

以上所述是小編給大家介紹的html5利用canvas實現顏色容差摳圖功能,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對武林網網站的支持!
如果你覺得本文對你有幫助,歡迎轉載,煩請注明出處,謝謝!

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
日韩暖暖在线视频| 亚洲伊人久久大香线蕉av| 日本不卡免费高清视频| 2019中文字幕在线免费观看| 91精品视频一区| 欧美大片欧美激情性色a∨久久| 欧美激情aaaa| 色青青草原桃花久久综合| 91精品国产91久久久久久久久| 亚洲欧美激情一区| 国产一区二区三区在线| 欧美黄色片视频| 精品久久香蕉国产线看观看gif| 久久综合电影一区| 久久久99免费视频| 91在线精品视频| 热久久美女精品天天吊色| 欧美精品videos| 51精品在线观看| 88国产精品欧美一区二区三区| 色综合视频网站| 欧美精品在线播放| 国产精品精品一区二区三区午夜版| 欧美亚洲成人精品| 国产成人精品免费久久久久| 欧美成人国产va精品日本一级| 91免费版网站入口| 日韩在线视频国产| 日韩精品极品毛片系列视频| 日韩女优人人人人射在线视频| 国产精品久久久久久久av电影| 午夜精品一区二区三区在线视频| 国产一区二区日韩| 97超级碰在线看视频免费在线看| 亚洲人成网在线播放| 国产精品一区专区欧美日韩| 日本伊人精品一区二区三区介绍| 另类天堂视频在线观看| 日韩中文字幕国产精品| 欧美精品在线免费播放| 激情成人在线视频| 国产一区二区三区四区福利| 欧美视频专区一二在线观看| 亚洲精品www久久久久久广东| 亚洲精品电影网| 粉嫩av一区二区三区免费野| 欧美成人激情在线| 欧美大片在线看免费观看| 国产美女搞久久| 日韩激情在线视频| 尤物九九久久国产精品的特点| 成人a视频在线观看| 播播国产欧美激情| 日韩少妇与小伙激情| 久久69精品久久久久久久电影好| 成人免费午夜电影| 成人免费在线视频网址| 黑人巨大精品欧美一区免费视频| 亚洲免费视频观看| 色综合久久久久久中文网| 岛国视频午夜一区免费在线观看| 久久在线免费观看视频| 欧美色xxxx| 色中色综合影院手机版在线观看| 国产亚洲欧美aaaa| 国产欧美va欧美va香蕉在线| 欧美成人精品三级在线观看| 91久久综合亚洲鲁鲁五月天| 精品国产精品三级精品av网址| 欧美成人午夜剧场免费观看| 久久精品国产96久久久香蕉| 欧美一区二区视频97| 国产精品91久久| 欧美在线观看视频| 亚洲欧美一区二区激情| 91免费版网站入口| 欧洲精品毛片网站| 欧美久久精品一级黑人c片| www.日本久久久久com.| 亚洲自拍偷拍色片视频| 欧美精品www在线观看| 欧美最猛性xxxx| 日本成人在线视频网址| 最新亚洲国产精品| 91午夜在线播放| 久久久久久久电影一区| 九九热视频这里只有精品| 精品久久久久久久久久久久| 国产精品色悠悠| 日韩国产欧美区| 久久久久日韩精品久久久男男| 日韩美女在线观看一区| 2018中文字幕一区二区三区| 亚洲欧美国产高清va在线播| 欧美性生活大片免费观看网址| 欧美精品www在线观看| 国产精品视频一区国模私拍| 欧美福利小视频| 日韩在线视频免费观看| 成人在线视频网站| 欧美日韩国产精品| 精品国产福利在线| 69av在线视频| 欧美性生交xxxxx久久久| 欧美国产中文字幕| 日韩网站在线观看| 成人av番号网| 亚洲图片欧美日产| 国产最新精品视频| 精品一区二区三区四区在线| 欧美午夜激情视频| 欧美性20hd另类| 精品自在线视频| 日韩欧美极品在线观看| 国产午夜精品视频免费不卡69堂| 欧美激情aaaa| 亚洲国产精品久久91精品| 久久国产精品首页| 亚洲摸下面视频| 日韩国产高清污视频在线观看| 精品动漫一区二区三区| 国产精品网址在线| 亚洲视频在线视频| 51色欧美片视频在线观看| 国产精品久久久久久久av大片| 亚洲精品国产成人| 91系列在线播放| 日本精品视频在线播放| 色悠悠国产精品| 亚洲精品ady| 欧美在线精品免播放器视频| 国产成人在线视频| 国产在线拍偷自揄拍精品| 97超碰国产精品女人人人爽| 欧美性猛交丰臀xxxxx网站| 亚洲电影免费观看高清完整版在线| 国产精品久久久久久久久久99| 亚洲视频国产视频| 欧美日本国产在线| 亚洲国产日韩欧美在线99| 久久综合久久美利坚合众国| 亚洲欧洲在线免费| 九九精品视频在线| 国产精品午夜国产小视频| 欧美激情在线狂野欧美精品| 国产一区二区丝袜| 青草青草久热精品视频在线观看| 欧美日韩精品中文字幕| 日韩国产精品一区| 91在线无精精品一区二区| 成人免费视频xnxx.com| 国产91露脸中文字幕在线| 日韩成人高清在线| 成人免费高清完整版在线观看| 91精品视频免费观看| 日韩高清免费观看| 欧美日韩亚洲一区二| 揄拍成人国产精品视频| 日韩精品免费在线观看| 精品国产91久久久久久| 亚洲男人的天堂网站| 欧美夫妻性视频| 全球成人中文在线| 久久视频在线免费观看|