2017-08-02 201 views
0

我正在开发一个应用程序,在该应用程序中,我在照片上运行繁重的算法。用户使用他的手机拍照,照片是动态的。然后,我使用插件为用户可以在广场上切脸。这是280px x 280px,的尺寸,并且会生成此尺寸的新图像。降低图像分辨率的最佳方法

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

我该怎么办? 我需要280像素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"; 
+0

像http://jsfiddle.net/xmae5p23/1/?虽然,你的代码没有提及280x280,只有200x200,但是委托人仍然是 –

+0

@JaromandaX那么,图像是否被优化? – yavg

+0

重新读取您的原​​始代码,它看起来像要将图像缩放到50x50,然后缩放到200x200? –

回答

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>

-1

你被告知什么是缩减图像只对分析(形状检测)。

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

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

通过在较小的画布上绘制原始图像并将较小的画布'ImageData传递到分析器,可以非常容易地实现它。但显然,你越会缩小图像,精度就会越低。

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 
 
    }; 
 
}
<canvas id="main"></canvas>

+0

这是很多代码来做OP任务,当它可以简单地用'ctx.drawImage(img,0,0,w,h)'来完成'...并且我不确定我是否看到了优势。另外,你如何推动一个'const'数组? – Toastrackenigma

+0

@Toastrackenigma,是的,这基本上是在做什么,但是它没有证明任何事情可以做到,在这里我做了一个模拟OP会做什么的例子,这就是为什么它不仅仅是需要... – Kaiido

+0

@Toastrackenigma,我不确定这个答案的意见是一个很好的地方,让我学习你的基本知识......所以用几句话:*优势*:40ms vs 9ms在我的机器上的一次性算法.. *'const'数组*:只有对象的引用是常量;它引用的对象仍然是可变的。 – Kaiido

相关问题