In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-14 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/01 Report--
This article introduces the "how to use canvas to achieve color tolerance matting" related knowledge, in the actual case of the operation process, many people will encounter such a dilemma, then let the editor lead you to learn how to deal with these situations! I hope you can read it carefully and be able to achieve something!
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) / / A pair of white matting is performed with a tolerance of 0.2} function cutout (canvas, color, range = 0) {let context = canvas.getContext ('2d'); let imageInfo = context.getImageData (0,0, canvas.width, canvas.height); / / pixiArr is an array in which every four array elements represent one pixel, each of which corresponds to a pixel of rmagg. Let pixiArr = imageInfo.data; for (let I = 0; I < pixiArr.length; I + = 4) {/ / set the alpha of the target pixel to 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; iTunes +) {if (! ((1-range) * target [I] = current [I]) return false;} return true;}
The three parameters of the testColor (current, target, range) method are the rgb array of the pixels to be detected, the rgb array of the target pixels and the tolerance range. Here the tolerance is simply calculated and compared by multiplying the values of r, g and b by (1 + range) and (1-range) respectively. Different tolerance parameters will get different effects ↓.
Range = 0.095
Range = 0.1
Range = 0.2
Of course, there is no need for tolerance for solid-color pictures with a standard background.
Boundary treatment
But sometimes we want to have a boundary so that the matting operation does not affect the pixels inside the boundary. For example, the picture above, we hope it will not affect the pixels inside the avatar. If we look at it line by line, can we achieve the effect as long as we stop the operation when we encounter a pixel that is not a boundary?
We scan each row separately, defining a left pointer left pointing to the first pixel of the line, defining a right pointer right pointing to the last pixel of the line, and using a leftF to identify whether the left touches the boundary, a rightF indicating whether the right touches the boundary, and shrinking inward when the pointer does not touch the boundary. Jump to the next line until both pointers touch the boundary or the left and right pointers coincide, until all lines are scanned.
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; / / points to line header pixel let right = left + 4 * canvas.width-1-3 / / indicates whether the left pointer touches the boundary of the pixel at the end of the line let leftF = false; / / let rightF = false / / whether the right pointer touches the boundary identifier while (! leftF | |! rightF) {/ / when both the left and right pointers are true, that is, the end if (! leftF) {if ([pixiArr [left], pixiArr [left + 1], pixiArr [left + 2], color, range) {pixiArr [left + 3] = 0 / / set the alpha of this pixel to 0 left + = 4; / / move to the next pixel} else leftF = true / / encounter the boundary} 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) {/ / left and right pointers coincide leftF = true; rightF = true;};}} context.putImageData (imageInfo, 0,0);}
Although probably completed our needs, but take a look at the hair above why there is an extra piece of white
Because we only have a row scan, the scan will stop when the left pointer touches the hair, but the inside of the hair Radian cannot be scanned. We also need to do a column scan to modify the above method:
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;};}} / / similarly perform column scan for (let col = 0; col < canvas.width; col++) {let top = col * 4 / / pointing to the column header let bottom = top + (canvas.height-2) * canvas.width * 4 + canvas.width * 4; / / pointing to the end of the column 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);}
As for why top and bottom calculate and draw a matrix graph in that way, you will probably know.
↓ after treatment
In fact, pixiArr can also be packaged as a matrix in pixels.
[[{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}]]
After processing, it is easier to calculate the pixel subscript. When the column is scanned, the matrix is rotated first, and then processed with a row scan. This way to deal with pixiArr is also conducive to further optimization of the algorithm.
Although the above method probably completes the matting effect, there are still many cases that this simple processing will not take into account.
For example, on the right side of the hair, this is the area ↓ that can't be touched by row scan or column scan.
The following clothes are also erased directly from the column scan because the color is the same as the background color and there is no boundary.
"how to use canvas to achieve color tolerance matting" content is introduced here, thank you for reading. If you want to know more about the industry, you can follow the website, the editor will output more high-quality practical articles for you!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.