我需要帮助来优化这个 Javascript 程序 - 表情符号相机转换器

问题描述 投票:0回答:0

这个程序是一个艺术项目,它将摄像机的像素转换成表情符号。 我做了一个光标来控制表情符号的数量,表情符号越多,分辨率越好,但视频速度越慢.... 我不是程序员,一个月前我自学了javascript。 如果您有任何使该程序更快运行的建议,请随时与我联系。

https://github.com/efka04/EmojiArt

我想我在绘图循环中使用了太多函数,这使程序变慢了。我还将颜色值从 rgb 转换为 hex,将 hex 转换为 rgb,但也许有更直接的解决方案,无需每次都转换颜色值。

// variables------
//let switchFlag = false;
let slider;
let video;
let asciiDiv;
const emojiHexadecimal = [];
const getAvgHex = (color, total) => {
  const hex = Math.round(color / total).toString(16);
  return hex.length === 2 ? hex : '0' + hex;
};

// --------

function componentToHex(c) {
  const hex = c.toString(16);
  return hex.length == 1 ? "0" + hex : hex;
}

//Convert RGB values to Hexadecimal -
function rgbToHex(r, g, b) {
  return "#" + componentToHex(r) + componentToHex(g) + componentToHex(b);
}

//Find the Distance between 2 colors (in RGB) --------------------
function distance(a, b) {
    return Math.sqrt(((a.r - b.r) ** 2) + ((a.g - b.g) ** 2) + ((a.b - b.b) ** 2));

}

//Convert headecimal values to RGB -
function hexToRgb(hex) {
      const shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
      hex = hex.replace(shorthandRegex, function(m, r, g, b) {
        return r + r + g + g + b + b;
      });
      const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
      return result ? {
        r: parseInt(result[1], 16),
        g: parseInt(result[2], 16),
        b: parseInt(result[3], 16)
      } : null;
    }

//Compare pixels colors with emoji list color -
function nearestColor(colorHex) {
  let lowest = Number.POSITIVE_INFINITY;
  let index = 0;
  for (let i = 0; i < emojiHexadecimal.length; i++) {
    const tmp = distance(hexToRgb(colorHex), emojiHexadecimal[i]);
    if (tmp < lowest) {
      lowest = tmp;
      index = i;
    }
  }
  return emoji[index];
}

//- SETUP -

function setup(){

  let switchBtn;
  const options = {
       video: {
           facingMode: {
            exact: "user"  }
  } };
  noCanvas();
  video = createCapture(options, VIDEO);
  video.size(540,960); //9:16
  asciiDiv = createDiv();
  asciiDiv.parent("screen");
  asciiDiv.style('background-color', 'black');
  asciiDiv.style('text-align', 'center');
  asciiDiv.style('font-size', '7px');
  asciiDiv.style('line-height', '7px');

  background(200);
  textAlign(CENTER);
  text('Click to play!', width / 2, height / 2);

  const emojiLength = emoji.length;

  for(let j = 0; j < emojiLength; j++ )
  {
    let totalPixels = 0;
    const colors = {
              red: 0,
              green: 0,
              blue: 0,
            };
        const canvas = document.createElement("canvas");
        const ctx = canvas.getContext("2d");
        //transform emoji to picture of 10x10 pixels
        ctx.fillText(emoji[j], 0, 10);
        const { data: imageData } = ctx.getImageData(0, 0, 10, 10);
        //take all pixels of the picture and make an average color
        for (let i = 0; i < imageData.length; i += 8) {
          let [r, g, b, a] = imageData.slice(i, i + 8);
          if (a > 50) {
            totalPixels += 1;
            colors.red += r;
            colors.green += g;
            colors.blue += b;
          }
        }
        const r = getAvgHex(colors.red, totalPixels);
        const g = getAvgHex(colors.green, totalPixels);
        const b = getAvgHex(colors.blue, totalPixels);
        emojiHexadecimal[j] = hexToRgb(r+g+b);//store rgb value in an array

        //reset Values of the emoji
        totalPixels = 0;
        colors.red = 0;
        colors.green = 0;
        colors.blue = 0;
        }
        //Slider
          colorMode(HSB);
          slider = createSlider(10, 30, 20, 2);
          slider.position(10, 15);
          slider.style('width', '300px');
        //Button
          switchBtn = createButton('Switch Camera');
          switchBtn.position(10, 40);
          switchBtn.style('font-size', '50px');
          switchBtn.mousePressed(switchCamera);
}

//----------
function switchCamera()
{
  const options = {
       video: {
           facingMode: {
            exact: "user"  }
  } };
  switchFlag = !switchFlag;
  if(switchFlag==true)
  {
   video.remove();
   options = {
     video: {
         facingMode: {
          exact: "environment"  }
     }};}
  else
  {
   video.remove();
   options = {
     video: {
         facingMode: {
          exact: "user"}
        } };}
  video = createCapture(options, VIDEO);
  video.size(540,960); //9:16
}

//---------
function draw(){
  background(255,0,0);
  video.loadPixels();

  let val = slider.value();
  let currentFont = (Math.exp(val*0.1)+5);
  asciiDiv.style('font-size', parseInt(currentFont) + 'px');
  asciiDiv.style('line-height', parseInt(currentFont) + 'px');

let asciiImage = ''; // emojis are stored here
const videoHeight = video.height;
const videoWidth = video.width;
// for every 3 pixels of the video
for (let j = 0; j < videoHeight; j = j + val){
  for (let i = 0; i < videoWidth ; i = i + val){
      // 1- find the pixel index
      const pixelIndex = (i + j * videoWidth) * 4;
      // 2- store every colors into 3 variables
      const r = video.pixels[pixelIndex + 0];
      const g = video.pixels[pixelIndex + 1];
      const b = video.pixels[pixelIndex + 2];
      // 3- find the average color
      const avg = (r + g + b)/3;
      const len = emoji.length;
      const charIndex = floor(map(avg,0,255,len,0));
      //4 - transform 3 rgb variables into one hexadecimal value
      const hex = rgbToHex(r, g, b);
      //5 - store into c the nearest color --> return an emoji from the list
      const c = nearestColor(hex); // return emoji[i]
    asciiImage = asciiImage + c; //add each emojis to the line
    }
    asciiImage += '<br/>' // one the line is over make a line jump
  }//loop end
    asciiDiv.html(asciiImage);
}//draw End
// ------------

谢谢

javascript camera p5.js emoji live
© www.soinside.com 2019 - 2024. All rights reserved.