乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      用canvas 實(shí)現(xiàn)個(gè)圖片三角化(LOW POLY)效果

       mediatv 2020-03-10

        之前無(wú)意中看到Ovilia 用threejs做了個(gè)LOW POLY,也就是圖片平面三角化的效果,覺(jué)得很驚艷,然后就自己花了點(diǎn)時(shí)間嘗試了一下。

        我是沒(méi)怎么用過(guò)threejs,所以就直接用canvas的2d繪圖API來(lái)做,因?yàn)楦杏X(jué)似乎這效果也用不上threejs。

        直接上demo先:http://whxaxes./canvas-test/src/Funny-demo/lowpoly/index.html   (也可以在移動(dòng)端看,不過(guò)因?yàn)橛?jì)算量比較大,移動(dòng)設(shè)備計(jì)算起來(lái)會(huì)比PC要多花些時(shí)間。)

        做這種效果主要需要把圖片三角化,以及對(duì)圖片進(jìn)行邊緣化檢測(cè)。這兩個(gè),第一個(gè)用到的delaunay三角化算法,第二個(gè)用到的sobel邊緣檢測(cè)算法。聽(tīng)起來(lái)偷挺高大上的,索性兩個(gè)算法都有相應(yīng)的開(kāi)源組件可以直接拿來(lái)用:ironwallaby的delaunay組件  以及 Miguel Mota的sobel組件。

        這兩個(gè)算法sobel還好一點(diǎn),delaunay就有點(diǎn)復(fù)雜了,待日后可以研究一下。不過(guò)目前只為做出個(gè)效果的話,還是可以用這些組件的。

        兩個(gè)最重要的組件都有了,剩下的事就很簡(jiǎn)單了:

        先將圖片繪制到canvas上:

      canvas.width = (img.width > 800) ? 800 : img.width;
      canvas.height = img.height * canvas.width/img.width;
      
      ctx.drawImage(img, 0, 0, canvas.width, canvas.height);

        然后獲取到canvas的imgData,再通過(guò)sobel計(jì)算返回新的imgData

       var imgData = ctx.getImageData(0, 0, canvas.width, canvas.height);var newImgData = Sobel(imgData);

         如果我們把newImgData放到canvas上,就會(huì)發(fā)現(xiàn),彩色圖片變成了這樣的灰度圖片:

        

        由于上面說(shuō)的那個(gè)Sobel組件不是很適合自己的用法,同時(shí)代碼也有不恰當(dāng)?shù)牡胤剑宰约鹤隽诉m當(dāng)修改和優(yōu)化,優(yōu)化了循環(huán)方法,加快了運(yùn)算速度,同時(shí)加入了回調(diào)函數(shù)。詳見(jiàn)該項(xiàng)目github中的sobel.js文件

        在Sobel方法中對(duì)imgData.data進(jìn)行遍歷的時(shí)候,會(huì)調(diào)用回調(diào)函數(shù),在回調(diào)中把顏色值大于40(也就是灰度為rgb(40,40,40)以上的)的坐標(biāo)點(diǎn)記錄下來(lái)。然后隨機(jī)獲取一部分邊緣點(diǎn),再加入一些隨機(jī)出來(lái)的坐標(biāo) 以及 四個(gè)邊角的坐標(biāo)值。這樣,我們就可以獲取到我們需要的坐標(biāo)點(diǎn)了

      復(fù)制代碼
              var imgData = ctx.getImageData(0, 0, canvas.width, canvas.height);//          收集色值大于40的邊緣像素點(diǎn)var collectors = [];
                  Sobel(imgData , function(value , x , y){if(value > 40){collectors.push([x , y]);}
                  });//          添加一些隨機(jī)點(diǎn)for(var i=0;i<300;i++){particles.push([Math.random()*canvas.width , Math.random()*canvas.height]);}//          添加隨機(jī)邊緣點(diǎn),數(shù)量為邊緣點(diǎn)數(shù)量除于50var length = ~~(collectors.length/50), random;for(var l=0;l<length;l++){
                      random = (Math.random()*collectors.length)<<0;
                      particles.push(collectors[random]);
                      collectors.splice(random , 1);
                  }//          添加四頂點(diǎn)坐標(biāo)particles.push([0,0] , [0,canvas.height] , [canvas.width,0] , [canvas.width,canvas.height]);
      復(fù)制代碼

        獲取到坐標(biāo)點(diǎn)后,就可以通過(guò)delaunay組件計(jì)算,獲取到拍好次序的三角坐標(biāo)數(shù)組,對(duì)這些數(shù)組里的點(diǎn)進(jìn)行連線,就可以出現(xiàn)這樣的效果:

        

         當(dāng)然,我們要的效果不是連線,而是對(duì)所有三角形進(jìn)行顏色填充,也就是獲取三角形的三個(gè)坐標(biāo),然后計(jì)算出中心點(diǎn)的坐標(biāo),再根據(jù)中心點(diǎn)坐標(biāo)在imgData里獲取到相應(yīng)的rgb的顏色值,然后填充到三角區(qū)域就可以了:

      復(fù)制代碼
      //        使用delaunay三角化獲取三角坐標(biāo)var triangles = Delaunay.triangulate(particles);var x1,x2,x3,y1,y2,y3,cx,cy;for(var i=0;i < triangles.length; i+=3) {
          x1 = particles[triangles[i]][0];
          x2 = particles[triangles[i+1]][0];
          x3 = particles[triangles[i+2]][0];
          y1 = particles[triangles[i]][1];
          y2 = particles[triangles[i+1]][1];
          y3 = particles[triangles[i+2]][1];//            獲取三角形中心點(diǎn)坐標(biāo)cx = ~~((x1 + x2 + x3) / 3);
          cy = ~~((y1 + y2 + y3) / 3);//            獲取中心點(diǎn)坐標(biāo)的顏色值index = (cy*imgData.width + cx)*4;var color_r = imgData.data[index];var color_g = imgData.data[index+1];var color_b = imgData.data[index+2];//            繪制三角形ctx.save();
          ctx.beginPath();
          ctx.moveTo(x1, y1);
          ctx.lineTo(x2, y2);
          ctx.lineTo(x3, y3);
          ctx.closePath();
          ctx.fillStyle = "rgba("+color_r+","+color_g+","+color_b+",1)";
          ctx.fill();
          ctx.restore();
      }
      復(fù)制代碼

        上面有一點(diǎn)要注意,獲取到的中心點(diǎn)坐標(biāo)一定要取整,才能夠獲取到正確的顏色參數(shù),如果想著不取整,而是在獲取rgb索引的時(shí)候再取整,獲取到的顏色值就是錯(cuò)的。因?yàn)檫@樣獲取到的那個(gè)像素點(diǎn)就不是我們要的中心像素點(diǎn)。

        顏色也獲取到后,就是簡(jiǎn)單的連線,然后填充操作了,最后出來(lái)的效果就是:

        

        雖然沒(méi)有設(shè)計(jì)師手動(dòng)描出來(lái)的好看,不過(guò)也方便很多,做來(lái)玩玩還是挺有意思的。

        本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評(píng)論

        發(fā)表

        請(qǐng)遵守用戶 評(píng)論公約

        類(lèi)似文章 更多