降低图像分辨率的最佳方法

时间:2017-08-02 03:50:35

标签: javascript

我正在开发一个应用程序,其中我在照片上运行繁重的算法。用户使用他的手机拍照,照片是动态的。然后我使用插件为用户可以在一个正方形切割他的脸。这是280px x 280px,的大小,会生成此尺寸的新图像。

我对这个主题知之甚少,但他们告诉我必须降低图像的分辨率以优化算法的执行时间,因为在蜂窝中我需要的程序会延迟一点。我有这个代码不是我的,我需要减小图像的大小,以优化执行算法所需的时间,但不会扭曲或像素化图像。

我该怎么办? 我需要有280px x 280像素的图像,但不会丢失质量。我需要优化它。

http://jsfiddle.net/xmae5p23/

var w = 200,
    h = 200,
    p = 50,
    q = 50;

var img = $("img").get(0);

img.onload = function() {
    cv.width = p;
    cv.height = q;

    ctx.drawImage(img, 0, 0, p, q);

    cv.style.width = w + "px";
    cv.style.height = h + "px";
};

img.src = "https://www.enterprise.com/content/dam/global-vehicle-images/cars/FORD_FOCU_2012-1.png";

2 个答案:

答案 0 :(得分:1)

您可以使用JavaScript将图片缩小到50px 50px,然后使用CSS将其缩放回200px 200px。什么?

我简化了你的代码。它现在不再需要pq参数,只需使用JavaScript将图像缩放为wh即可。我还删除了使用CSS缩放图像的代码,因为它是多余的。



var cv = $("#cv").get(0),
    ctx = cv.getContext("2d");

//Paint image using specified width and height
var w = 200,
    h = 200;

var img = $("img").get(0);

img.onload = function() {
    cv.width = w;
    cv.height = h;
    
    ctx.drawImage(img, 0, 0, w, h);
};

img.src = "https://www.enterprise.com/content/dam/global-vehicle-images/cars/FORD_FOCU_2012-1.png";

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<canvas width="400" height="400" id="cv"></canvas>
<br>
Original:
<br>
<img>
&#13;
&#13;
&#13;

答案 1 :(得分:-1)

您被告知的是仅为分析(形状检测)缩小图像尺寸。

您的算法可能会在搜索模式的图像中包含的整个像素上多次迭代。

通过缩小原始图像的大小,您还可以减少要分析的像素数,从而提高分析的性能。

通过在较小的画布上绘制原始图像,并将此较小的画布'ImageData传递给分析器,您可以非常轻松地实现它。但显然,你缩小图像的次数越多,你得到的精确度就越低。

SELECT
    prod_id,
    product,
    technology,
    price,
    quantity
FROM tbl_product t1
WHERE (SELECT SUM(t2.quantity) FROM tbl_product t2
       WHERE t2.prod_id <= t1.prod_id) < @quantity
const img = new Image();
img.crossOrigin = 'anonymous';
img.onload = init;
img.src = 'https://upload.wikimedia.org/wikipedia/commons/5/55/John_William_Waterhouse_A_Mermaid.jpg';

function init() {
  const ctx = main.getContext('2d');
  main.width = img.width;
  main.height = img.height;
  ctx.drawImage(img, 0, 0);
  // we'll look for these green squares
  ctx.fillStyle = '#FF00FF';
  for (let i = 0; i < 4; i++) {
    ctx.fillRect(Math.random() * img.width, Math.random() * img.height, 10, 10);
  }
// First try with the full Image
  ctx.strokeStyle = '#00FF00';
  let t1 = performance.now();
  const big_area = findShapes(ctx.getImageData(0, 0, img.width, img.height));
  console.log(`full_size (green) took ${performance.now() - t1}ms`);
  ctx.strokeRect(big_area.x, big_area.y, big_area.width, big_area.height);
  
// Now with the downscaled one
  ctx.strokeStyle = 'blue';
  t1 = performance.now();
  const area = scaleAndfindShapes(main);
  console.log(`down_sized (blue) took ${performance.now() - t1}ms`);
  ctx.strokeRect(area.x, area.y, area.width, area.height);
}

function scaleAndfindShapes(main) {
  // first we create a smaller canvas
  const ratio = main.height / main.width;
  const canvas = document.createElement('canvas');
  canvas.height = canvas.width * ratio; // max width : 300px

  const scale = main.width / canvas.width;
  const ctx = canvas.getContext('2d');
  // draw the orignal image on this downscaled canvas
  ctx.drawImage(main, 0, 0, canvas.width, canvas.height);
  // take the imageData from this smaller canvas
  const img = ctx.getImageData(0, 0, canvas.width, canvas.height);

  const rect = findShapes(img);
  // return our bounding rect, rescaled to the main canvas size
  return {
    x: rect.x * scale,
    y: rect.y * scale,
    width: rect.width * scale,
    height: rect.height * scale
  };

}

function findShapes(img) {
  const data = img.data;
  // search for something (here purple pixels)
  const px_indice = [];
  for (let i = 0; i < data.length; i += 4) {
    if (data[i] > 254 && data[i + 2] > 254) {
      px_indice.push(i / 4);
    }
  }
  // just build a bounding rect...
  const px_pos = px_indice.map(i => {
    let r = i / img.width,
      y = ~~r;
    return {
      x: Math.round((r - y) * img.width),
      y: y
    };
  });
  const min_x = Math.min.apply(null, px_pos.map(p => p.x));
  const max_x = Math.max.apply(null, px_pos.map(p => p.x));
  const min_y = Math.min.apply(null, px_pos.map(p => p.y));
  const max_y = Math.max.apply(null, px_pos.map(p => p.y));
  return {
    x: min_x,
    width: (max_x - min_x),
    y: min_y,
    height: max_y - min_y
  };
}