国产激情自拍_国产9色视频_丁香花在线电影小说观看 _久久久久国产精品嫩草影院

首頁 > 開發 > 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實現顏色容差摳圖功能,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對武林網網站的支持!
如果你覺得本文對你有幫助,歡迎轉載,煩請注明出處,謝謝!

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
国产激情自拍_国产9色视频_丁香花在线电影小说观看 _久久久久国产精品嫩草影院
久久一本精品| 一本免费视频| 中文字幕在线视频观看| 国产尤物一区二区三区| 国产美女自拍视频| 国产经典自拍视频在线观看| 在线中文字幕观看| 碰草在线视频| 国产精品69一区二区三区| 一区二区三区免费视频网站| 青青国产在线| 另类综合图区| 精品无人乱码| 国产在线视频精品视频免费看| 综合激情亚洲| 日本高清不卡中文字幕| 国产三级av在线| 蜜桃av网站| 国产激情在线视频| 毛片在线视频| 精品日韩av| 国产精品自产拍在线网站| 在线影视一区| 国产一二三区精品视频| 男人天堂亚洲| 午夜羞羞小视频在线观看| 国产精品人人| 国产你懂的在线观看| 在线观看的网站你懂的| 国产羞羞视频在线播放| 青青草原av在线| 亚洲精品视频区| av免费在线一区二区三区| 国产欧美日韩精品综合| 成人精品一区二区三区免费| а√最新版在线天堂| 18av在线视频| 99热免费观看| 在线看a视频| 亚洲私人影吧| 青青草视频在线观看| 天天插天天狠天天透| 精品视频一二区| 91久久精品国产性色| 国产精品黄页网站在线播放免费| 午夜视频免费在线观看| 国产在线免费观看| 福利资源在线久| 最新天堂资源在线资源| 国产一二三区在线| 国产二级片在线| 在线免费观看高清视频色| 99久久国产视频| 亚洲国产日韩成人综合天堂| 青青草中文字幕| 丁香花高清在线观看完整版 | 成年黄网站在线观看免费| 亚洲男人网站| 久草.com| 国产深夜福利| 伊人网站在线| 国自产拍在线网站网址视频| 国产一区二区在线|播放| 国产精品二线| 欧美日韩在线视频免费观看| 国产精品一区二区资源| 国产小视频在线| 97国产视频| 国产中文在线| 制服丝袜中文字幕在线观看| 日本成人a视频| 国产高清免费av在线| 亚洲videos| 国产一起色一起爱| 中文字幕av在线| 中文字幕在线观看播放| 99久久99久久免费精品小说| 免费国产在线视频| 在线伊人免费视频| 国产麻豆一区二区三区精品| 欧美日韩在线视频免费观看| 国产小视频在线高清播放| 性国产高清在线观看| 国产网站在线播放| 黄色av网站在线| 日韩黄色成人| 在线观看电影av| 精品国内自产拍在线视频| 天堂资源中文在线| 激情网站在线| 另类综合图区| 欧美激情福利视频在线观看免费| 中文在线视频观看| 国产aa视频| 国产精品日日爱| 国产亚洲精品午夜高清影院| 青草在线视频在线观看| 在线观看av资源网| 影音av资源站| 一区二区三区四区在线免费视频| 国产精品久久久久白浆| 国产小视频免费在线观看| 国产男女无套在线播放| 国产中文字幕网| 好男人社区在线视频| 国产资源在线看| 尤物视频网站在线观看| 中文字幕在线观看日本| 国产一区电影| 91社区在线观看| 在线黄色.com| 小说区乱图片区| 日本高清中文字幕二区在线| xxx国产精品| 丁香花高清视频完整版在线观看| 国产在线三区| 国产黄色大片在线观看| 99综合精品久久| 久热久精久品这里在线观看| 中文字幕在线播放网址| 国产xxxx做受性欧美88| 亚洲精品一线| 天天爱天天色| 9999在线视频| 国内精品一区视频| 精品国产丝袜高跟鞋| 亚洲成人av高清| 国产亚洲依依| 女人色在线免费视频| 午夜在线小视频| 亚洲国产日韩成人综合天堂| 成视频年人免费看黄网站| 国产成人午夜| 最新天堂资源在线| av在线网页| 国产啊啊啊视频在线观看| 黄色一级视频网站| 天天操夜夜做| 精品国产福利一区二区在线 | 欧美韩日国产| 国产精品乱码一区二区三区视频| 四虎成年永久免费网站| 午夜视频99| 六月天色婷婷| 99reav在线| 国产精品合集一区二区| 麻豆精品永久免费视频| 777电影在线观看| 国产一级网站视频在线| 高清av中文在线字幕观看1| 中文天堂av| 国产精品国产国产aⅴ| 国产精选在线视频拍拍拍| www.操.com| 中文在线官网天堂| 97视频网站| 国产成a人亚洲精v品| 国产特黄在线| 国产精品午夜久久久久久| 欧美日韩在线精品成人综合网| 精品国产美女福利到在线不卡| 国产一卡2卡3卡4卡网站免费| 国产在线资源| 午夜视频免费在线观看| 开心丁香婷婷深爱五月| 麻豆av电影在线观看| 老师我好爽再深一点的视频| 免费久久网站| 国产资源在线看| 二人午夜免费观看在线视频| 美女av在线播放| 在线91av| 在线视频99| 就爱干草视频| 国产精品入口麻豆免费观看| 精品一区二区三区在线观看l| 精品一二三区视频| 欧美日韩一区二区三区视视频| 久久精品蜜桃| 国产福利视频在线观看| 一本免费视频| 激情丁香久久| 国产精品欧美色图| 四虎成人免费| 毛片网站在线观看| 国产无遮挡又黄又爽免费网站| 国产成在线观看免费视频| 天天插天天干| 国产三区在线观看| 免费a级人成a大片在线观看| 日本中文字幕视频| 精品国内自产拍在线视频| 欧洲亚洲精品视频| 国产精品视频h| 久久亚洲资源| 一本大道久久a久久精品| 丁香婷婷激情| 亚洲综合在线网| 国产黄色在线观看| 免费a在线看|