1. 程式人生 > >canvas影象畫素處理- 馬賽克/濾鏡(一)

canvas影象畫素處理- 馬賽克/濾鏡(一)

一.要注意的問題
在chrome下會發生錯誤
Uncaught SecurityError: 
Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The canvas has been tainted by cross-origin data.
大概意思就是發生了跨域操作,也就是指圖片的來源和當前的網頁來源不同時,造成了跨域。
據說放到伺服器上載入就會解決這個問題;我放到了本地的伺服器環境可以順利執行。以後凡是用到getImageData函式的地方,一定要使用此方法進行測試,此處不贅述。

二.知識點:

1.圖片的載入:
var img=new Image();
img.src = "timg.jpg";
img.onload=function (){
context.drawImage( image , 0 , 0 );
}
2.
getImageData() 從Canvas畫板上取得所選區域的畫素資料

圖片資料讀取完成後,首先將圖片資料繪製到Canvas畫板上,用getImageData函式從畫板上取得畫素資料。

var imgData=context.getImageData(x,y,width,height);

x,y開始複製的起點座標 width,height選擇區域的長和寬

② ImageData 物件,該物件拷貝了畫布指定矩形的畫素資料。


最後分析結果:data: 含有ImageData 物件所有的畫素,每個畫素都存在著四個值的資訊,分別是r,g,b,a

 這是一個簡單畫素處理:var pixelData = imageData.data;
            for(var i=0;i<canvas.width*canvas.height;i++){
                pixelData[4*i+0]=0;
                pixelData[4*i+1]=0;
                // pixelData[4*i+2]=0;
            }

 這是一個簡單畫素深淺處理:

var pixelData = imageData.data;

            for(var i=0;i<canvas.width*canvas.height;i++){
                var r = pixelData[i*4+0];
                var g = pixelData[i*4+1];
                var b = pixelData[i*4+2];

                var grey = r*0.3+g*0.59+b*0.11;//這個演算法是影象學家研究出對RGB深淺的最好值


                pixelData[i*4+0] = grey;
                pixelData[i*4+1] = grey;
                pixelData[i*4+2] = grey;
            }

這是二維陣列:遍歷每一個畫素

 for( var i = 0 ; i < canvas.height ; i ++ )
                for( var j = 0 ; j < canvas.width ; j ++ ){

//遍歷第i行第j列的時候對應canvas的位移
                    var p = i*canvas.width + j;
                    //每一個點的畫素值
                    pixelData[p*4+0] =
r;
                    pixelData[p*4+1] =
g;
                    pixelData[p*4+2] =
b;

}
}

4.putImageData() 方法函式則表示將所得到的畫素資料描畫到Canvas畫板上形成圖形。

context.putImageData(imgData,x,y,dirtyX,dirtyY,dirtyWidth,dirtyHeight);

其中imgdata為畫素資料,dx、dy是繪製圖片的定位座標值,dirtyXdirtyY是imgdata所要繪製圖片的起始位置,dirtyXw、dirtyXh是imgdata所要繪製區域(相對imgdata的dirtyXx和dirtyXy座標的偏移量)的寬度和高度值。這裡面第4個引數以及其後的所有引數都可以省略,如果這些引數都省略了,則表示繪製整個imgdata。

5.getImageData函式從畫板上取得畫素資料然後通過 putImageData() 將所取得的畫素資料畫到Canvas畫板上
var imgData=ctx.getImageData(10,10,50,50);

整個畫素資料畫到Canvas畫板上:ctx.putImageData(imgData,10,70);

畫素資料的一部分畫到Canvas畫板上:ctx.putImageData(imgData,200,260,50,50,100,100); 

三.特效


<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <style type="text/css">
        .clearfix:after,.zn-clearfix:before{content: ""; visibility: hidden; display: block; height: 0; clear: both; }
        .clearfix{zoom:1;margin: 20px auto; width:1700px;}
    </style>
</head>
<body>
    <div class="clearfix">
        <canvas id="canvasa" width="800" height="560" style="display:block;float:left;border:1px solid #aaa;"></canvas>
        <canvas id="canvasb" width="800" height="560" style="display:block;float:right;border:1px solid #aaa;"></canvas>
    </div>
    <script>
        var canvasa = document.getElementById("canvasa");
        var contexta = canvasa.getContext("2d");

        var canvasb = document.getElementById("canvasb");
        var contextb = canvasb.getContext("2d");

        var image = new Image();

        window.onload = function(){

            image.src = "1.jpg";
            image.onload = function(){

                contexta.drawImage( image , 0 , 0 , canvasa.width , canvasa.height );
            }
        }
        
    </script>
</body>
</html>
(1).如何在影象中簡單影象處理

灰度濾鏡:


//灰度影響
        function greyEffect(){
            //通過 getImageData() 複製畫布上指定矩形的畫素資料,然後通過 putImageData() 將影象資料放回畫布:
            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[i*4+0];
                var g = pixelData[i*4+1];
                var b = pixelData[i*4+2];

                var grey = r*0.3+g*0.59+b*0.11;//這個演算法是影象學家研究出對RGB深淺的最好值

                pixelData[i*4+0] = grey;
                pixelData[i*4+1] = grey;
                pixelData[i*4+2] = grey;
            }
            contextb.putImageData( imageData , 0 , 0 ,0 , 0 , canvasb.width, canvasb.height);
        }

黑白濾鏡:是指影象上只有白色,黑色;也就是rgb(255,255,255),或是rgb(0,0,0)。


//黑白濾鏡:是指影象上只有白色,黑色;也就是rgb(255,255,255),或是rgb(0,0,0)。
        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[i*4+0];
                var g = pixelData[i*4+1];
                var b = pixelData[i*4+2];

                var grey = r*0.3+g*0.59+b*0.11;
                if(grey > 125){
                    pv = 255;
                }
                else{
                    pv = 0;
                }

                pixelData[i*4+0] = pv;
                pixelData[i*4+1] = pv;
                pixelData[i*4+2] = pv;
            }

            contextb.putImageData( imageData , 0 , 0 , 0 , 0 , canvasa.width , canvasa.height );
        }

反色濾鏡:是指影象上的每一個點的RGB值修改為255-原來的值


 //反色濾鏡:是指影象上的每一個點的RGB值修改為255-原來的值
        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[i*4+0];
                var g = pixelData[i*4+1];
                var b = pixelData[i*4+2];

                pixelData[i*4+0] = 255 - r;
                pixelData[i*4+1] = 255 - g;
                pixelData[i*4+2] = 255 - b;
            }

            contextb.putImageData( imageData , 0 , 0 , 0 , 0 , canvasb.width , canvasb.height );
        }

黑白,反色濾鏡的每一個畫素修改只需要參照自己當前的畫素。

(2).如何在影象中參考一個畫素周圍的其他畫素,進而實現一個影象處理

要注意:要保證周圍的畫素點不能被演算法所修改,所以就不能僅僅使用一個imageData,需要建立一個imageData的拷貝var tmpImageData.

此後就參考tmpImageData,來修改imageData,最終把imageData結果傳給putImageData,由此複製在畫布上,同時當函式執行putImageData時,tmpImageData也就拋棄了。
模糊濾鏡:模糊濾鏡則需要參考自己周圍的濾鏡,影象上的每一個點的RGB值為周圍的畫素的平均值。


function blurEffect(){
            var tmpImageData = contexta.getImageData( 0 , 0 , canvasa.width , canvasa.height );
            var tmpPixelData = tmpImageData.data;

            var imageData = contexta.getImageData( 0 , 0 , canvasa.width , canvasa.height );
            var pixelData = imageData.data;

            var blurR =3;//模糊的半徑
            //參考多少個畫素點(這個區域是正方形的面積)
            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;//來計算周圍所有的RGB的總和
                    //一個畫素點周圍有8個畫素點。
                    //二維迴圈編輯:基於中心點在x,y方向的位移的變化值,迴圈走了9次,
                    //下面這個就是點周圍的點迴圈+自身(i,j)
                    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];
                        }
                    }
                    //遍歷第i行第j列的時候對應canvas的位移
                    var p = i*canvasb.width + j;
                    //把周圍的畫素的平均值賦值(i,j)
                    pixelData[p*4+0] = totalr / totalnum;
                    pixelData[p*4+1] = totalg / totalnum;
                    pixelData[p*4+2] = totalb / totalnum;
                }
            }
            contextb.putImageData( imageData , 0 , 0 , 0 , 0 , canvasb.width , canvasb.height );
        }

馬賽克濾鏡:


馬賽克:一塊畫素的值=這塊全部畫素平均值

        //馬賽克:一塊畫素的值=這塊全部畫素平均值
        function mosaicEffect(){
            var tmpImageData = contexta.getImageData( 0 , 0 , canvasa.width , canvasa.height );
            var tmpPixelData = tmpImageData.data;

            var imageData = contexta.getImageData( 0 , 0 , canvasa.width , canvasa.height );
            var pixelData = imageData.data;
            //定義為一塊的邊長是多少(這個影象寬高的整數倍)
            var size = 16;
            var totalnum = size*size;
            for( var i = 0 ; i < canvasb.height ; i += size )
                for( var j = 0 ; j < canvasb.width ; j += size ){
                    //這塊是計算每一塊全部的畫素值--平均值
                    var totalr = 0 , totalg = 0 , totalb = 0;
                    for( var dx = 0 ; dx < size ; dx ++ )
                        for( var dy = 0 ; dy < size ; 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];
                        }

                    var p = i*canvasb.width+j;
                    var resr = totalr / totalnum;
                    var resg = totalg / totalnum;
                    var resb = totalb / totalnum;

                    //這個快畫素的值=它的平均值
                    for( var dx = 0 ; dx < size ; dx ++ )
                        for( var dy = 0 ; dy < size ; dy ++ ){

                            var x = i + dx;
                            var y = j + dy;

                            var p = x*canvasb.width + y;
                            pixelData[p*4+0] = resr;
                            pixelData[p*4+1] = resg;
                            pixelData[p*4+2] = resb;
                        }
            }
            contextb.putImageData( imageData , 0 , 0 , 0 , 0 , canvasb.width, canvasb.height );
        }

相關推薦

canvas影象處理- 馬賽克/()

一.要注意的問題 在chrome下會發生錯誤Uncaught SecurityError: Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The canvas has been tainted

canvas影象處理-createImageData()(二)

一.知識點 3. createImageData函式有兩種函式原型,其語法分別如下所示 (1).createImageData(sw, sh);  其一,返回指定大小的imageData物件。 (

canvas影象處理——實現效果

                                         實現濾鏡效果 點選按鈕出現不同濾鏡效果 首先,我們分析濾鏡的具體,主要就是對圖片的每個具體畫素進行處理,先拿到畫素,處理後再將畫素放回去。 1.怎樣拿到畫素         

python數字影象處理(3):影象的訪問與裁剪

圖片讀入程式中後,是以numpy陣列存在的。因此對numpy陣列的一切功能,對圖片也適用。對陣列元素的訪問,實際上就是對圖片畫素點的訪問。 彩色圖片訪問方式為: img[i,j,c] i表示圖片的行數,j表示圖片的列數,c表示圖片的通道數(RGB三通道分別對應0,1

Python-OpenCV 處理影象(三):影象點操作

https://segmentfault.com/a/1190000003742442 0x01. 畫素 有兩種直接操作圖片畫素點的方法: 第一種辦法就是將一張圖片看成一個多維的list,例如對於一張圖片im,想要操作第四行第四列的畫素點就直接 im[3,3] 就可以獲取到這個點的RGB值。 第二種就是

【程式語言】利用CImage類對影象處理影象二值化)

    最近做的課程作業需要用到CImage函式處理影象,其中涉及到讀取影象以及對影象畫素進行操作,在這裡記錄一下自己的理解。    首先是CImage類的定義和讀取圖片 CImage srcImage; CImage dstImage; CString path = "

影象處理影象隨機化:雪花漫天飛

近來經常和心理系做實驗,總是有各種“什麼什麼隨機化,刺激的物理性質保持一樣。。”的需求。之前做《去掩蔽》的實驗時,有一套圖片就是做的畫素隨機化,這是最簡單的隨機化了。當時影象只有兩種畫素,灰的和深灰的,而且深灰的比較少。於是我就統計了深灰畫素點的個數,然後在一張同樣大的灰色圖

Python 影象處理 OpenCV (2):處理與 Numpy 操作以及 Matplotlib 顯示影象

![](https://cdn.geekdigging.com/opencv/opencv_header.png) 前文傳送門: [「Python 影象處理 OpenCV (1):入門」](https://www.geekdigging.com/2020/05/17/5513454552/) ## 普通

影象點讀取和賦值

//取IplImage影象畫素值 int main() {     IplImage* src = cvLoad("filename",0); //-1預設讀取原通道,0 灰度圖,1彩色圖     if(src!=0)  &nb

OpenCV學習筆記(三)之影象的提取

     提取影象的畫素及畫素索引 Mat src, dst; src = imread("mountainandwater.jpg"); //讀取影象 if (src.empty()) { qDebug()<<"can

【電腦科學】【2017.11】【含原始碼】用於超光譜影象分類的深度學習研究

本文為荷蘭代爾夫特理工大學(作者:I.A.F. Snuverink)的碩士論文,共128頁。 在超光譜(HS)成像中,每一個畫素都要捕獲波長光譜,這些光譜代表材料性質,即光譜特徵。因此,HS影象的分類是基於材料屬性的。本文介紹了一種在不同環境條件下的固定場景中進行HS影象畫素分類的

訪問影象幾種方法

#include <iostream> #include <opencv2/opencv.hpp> #include <Windows.h> #include <opencv2/highgui/highgui.hpp> using namespace

opencv讀取影象值讀取並儲存到txt檔案(二)灰度圖

#include "stdafx.h" #include"cv.h" #include <stdlib.h> #include <stdio.h> #include <math.h> #include <fstream> #include &l

opencv讀取影象值讀取並儲存到txt檔案()RGB

#include “stdafx.h” #include"cv.h" #include <stdlib.h> #include <stdio.h> #include <math.h> #include #include #include “iost

sklearn:影象與平行隨機森林的重要性

此示例顯示了使用來評估影象分類任務(面)中畫素的重要性。 畫素越熱,越重要。下面的程式碼還說明了如何在多個任務中並行化預測的構造和計算。 print(__doc__) from time import time import matplotlib.pyplot as plt from s

openCV--訪問影象的三個方法

方法一       指標訪問:C操作符[ ] 方法二       迭代器iterater 方法三        動態地址計算 訪問速度上,debug模式下 ,方法一 > 方法二 > 方法

OpenCV二值化影象操作

二值化影象畫素不是0就是255,資料型別為uchar。所以訪問方法是: // 這裡inputmat是二值化影象的mat inputmat.at<uchar>(y, x); 判斷是否為白色的方法: if (inputmat.at<uchar&g

遍歷影象點的方法

一:椒鹽噪點的例子(隨機遍歷影象的某個畫素點) void salt(Mat &image,int n){ for(int k=0;k<n;k++){ //rand():隨機數產生函式 int i=rand()%image.cols; int j=r

OpenCV——修改影象(隨心所欲)

這一節將講述OpenCV——修改影象畫素,根據自己需要新增特定的畫素部分 原圖如下,我們就是先在這個視訊流上新增一條直線段(有一定寬度的) 現在我們想新增一條,135行-455行,列350--360的直線段 #include<opencv2/opencv.hp

opencv中對影象點訪問的三種方法利用程式進行解讀

程式碼放到自己的工程中,執行就可以的 #include <opencv2\opencv.hpp> #include <opencv2\core\core.hpp> #include <opencv2\highgui\highgui.hpp> #includ