canvas圖像處理
阿新 • • 發佈:2018-05-27
RR -o 演示 如果 算子 HA 參考 核心 邊緣檢測
最近在慕課網看到一個canvas圖像處理的教程,現在總結一下。 不多說其它了,開始說代碼吧。 以下canvasA是原圖的畫布,canvasB是處理後的圖像的畫布 RGB通道過濾
RGB通道過濾
function filter(){ var imageData = contextA.getImageData(0,0,canvasA.width,canvasA.height); //Uncaught SecurityError: Failed to execute ‘getImageData‘ on ‘CanvasRenderingContext2D‘: The canvas has been tainted by cross-origin data. //跨域認為是被汙染的 var pixelData = imageData.data; for(var i=0; i<canvasB.width*canvasB.height; i++){ pixelData[4*i+0] = 0; //r // pixelData[4*i+1] = 0; //g pixelData[4*i+2] = 0; //b } contextB.putImageData(imageData,0,0,0,0,canvasA.width,canvasA.height); }
可以看到其實就是獲取了像素點時候,把需要過濾掉的顏色置零就可以了
灰度化
function greyEffect(){ var imageData = contextA.getImageData(0,0,canvasA.width,canvasA.height); var pixelData = imageData.data; for(var i=0; i<canvasB.width*canvasB.height; i++){ var r = pixelData[4*i+0]; var g = pixelData[4*i+1]; var b = pixelData[4*i+2]; var grey = r*0.3 + g*0.59 + b*0.11; pixelData[4*i+0] = grey; pixelData[4*i+1] = grey; pixelData[4*i+2] = grey; } contextB.putImageData(imageData,0,0,0,0,canvasA.width,canvasA.height); }
就是通過一條算灰度的公式算出灰度值,然後把它賦給像素的rgb。
黑白二值化
function blackEffect(){ var imageData = contextA.getImageData(0,0,canvasA.width,canvasA.height); var pixelData = imageData.data; for(var i=0; i<canvasB.width*canvasB.height; i++){ var r = pixelData[4*i+0]; var g = pixelData[4*i+1]; var b = pixelData[4*i+2]; var grey = r*0.3 + g*0.59 + b*0.11; if( grey > 255 / 2){ v = 255; }else{ v = 0; } pixelData[4*i+0] = v; pixelData[4*i+1] = v; pixelData[4*i+2] = v; } contextB.putImageData(imageData,0,0,0,0,canvasA.width,canvasA.height); }
就是算出灰度後,判斷一下灰度是否大於255/2。如果是就認為該點是亮色,置為白色,否則,置為黑色。
反色
function reverseEffect(){ var imageData = contextA.getImageData(0,0,canvasA.width,canvasA.height); var pixelData = imageData.data; for(var i=0; i<canvasB.width*canvasB.height; i++){ var r = pixelData[4*i+0]; var g = pixelData[4*i+1]; var b = pixelData[4*i+2]; pixelData[4*i+0] = 255 - r; pixelData[4*i+1] = 255 - g; pixelData[4*i+2] = 255 - b; } contextB.putImageData(imageData,0,0,0,0,canvasA.width,canvasA.height); }
就是把像素的rgb變成255-rgb,就得到了相反的顏色
模糊算法
function blurEffect(){ //臨時保存樣板 var tmpData = contextA.getImageData(0,0,canvasA.width,canvasA.height); var tmpPixelData = tmpData.data; var imageData = contextA.getImageData(0,0,canvasA.width,canvasA.height); var pixelData = imageData.data; var blurR = 4; //模糊半徑 var totalnum = (2*blurR+1)*(2*blurR+1); //參考的像素點 for(var i=blurR; i<canvasB.height-blurR; i++){ for(var j=blurR; j<canvasB.width-blurR; j++){ var totalr = 0, totalg = 0, totalb = 0; for(var dx=-blurR; dx<=blurR; dx++){ for(var dy=-blurR; dy<=blurR; dy++){ var x = i + dx; var y = j + dy; var p = x*canvasB.width + y; totalr += tmpPixelData[p*4+0]; totalg += tmpPixelData[p*4+1]; totalb += tmpPixelData[p*4+2]; } } pixelData[4*i+0] = totalr / totalnum; pixelData[4*i+1] = totalg / totalnum; pixelData[4*i+2] = totalb / totalnum; } } contextB.putImageData(imageData,0,0,0,0,canvasA.width,canvasA.height); }
這個算法比之前的復雜許多,原理就是獲取當前像素點周圍的像素的rgb的平均值賦給當前像素點。
邊緣檢測
1.roberts算子
function roberts(){ //獲取像素點陣 var imageData = contextA.getImageData(0,0,canvasB.width,canvasB.height); var pixelData = imageData.data; //算法核心 for(var i = 0; i < canvasB.height-1; i++){ for(var j = 0; j < canvasB.width-1; j++){ //獲取需要像素下標 var target = 4*(i*canvasB.width+j); //左上 var member1 = 4*(i*canvasB.width+j+1); //右上 var member2 = 4*((i+1)*canvasB.width+j); //左下 var member3 = 4*((i+1)*canvasB.width+j+1); //右下 for(var k = 0; k < 3; k++){ var gx = pixelData[target+k] - pixelData[member3+k]; var gy = pixelData[member1+k] - pixelData[member2+k]; var vc = Math.abs(gx) + Math.abs(gy); pixelData[target+k] = vc; } } } contextB.putImageData(imageData,0,0,0,0,canvasB.width,canvasB.height); }
這個算法更復雜了,什麽閾值的我沒看懂,沒有用,發現效果還可以。
2.sobel算子
//sobel算子 function sobel(){ //獲取像素點陣 var imageData = contextA.getImageData(0,0,canvasB.width,canvasB.height); var pixelData = imageData.data; var fImageData = contextA.getImageData(0,0,canvasB.width,canvasB.height); var fData = fImageData.data; //拷貝pixelData //旋轉後的卷積核 var gxData = [ [1,0,-1], [2,0,-2], [1,0,-1] ]; var gyData = [ [1,2,1], [0,0,0], [-1,-2,-1] ]; //算法核心 for(var i = 1; i < canvasB.height-1; i++){ for(var j = 1; j < canvasB.width-1; j++){ //獲取需要像素下標 var target = 4*(i*canvasB.width+j); var gx = [0,0,0]; //r,g,b var gy = [0,0,0]; for(var dx = -1; dx <= 1; dx++){ for(var dy = -1; dy <= 1; dy++){ var x = i + dx; var y = j + dy; var p = 4*(x*canvasB.width + y); //rgb分別計算 for(var k = 0; k < 3; k++){ gx[k] += (fData[p+k] * gxData[dx+1][dy+1]); gy[k] += (fData[p+k] * gyData[dx+1][dy+1]); } } } for(var k = 0; k < 3; k++){ var vc = Math.abs(gx[k]) + Math.abs(gy[k]); pixelData[target+k] = vc; } } } contextB.putImageData(imageData,0,0,0,0,canvasB.width,canvasB.height); }
效果:
demo演示
canvas圖像處理