使用javascript比较旋转的图像

西乔

我有一个样本图像和一组其他图像,我想将它们与第一张图像进行比较。因此,我将它们都绘制到画布上并检查它们是否相同。

我在这里使用了这个概念:比较JavaScript中的两个图像

问题在于图像以随机角度旋转。因此图片的base64值似乎彼此不匹配。

注意:我无法计算角度,试错法会浪费资源

match=-1;
for(i=0;i<7;i++)
        {
            context1.drawImage(img,xPos[i],5,width[i],height,0,0,width[i],height);;
                if(canvas1.toDataURL()==samplecanvas.toDataURL()){
                    match=i+1;
                    break;
                }

            context1.clearRect(0, 0, canvas1.width, canvas1.height);
        }

在上面的代码中,我正在遍历图像。我在给定的样本图像samplecanvascanvas1是我画我的图片列表。那我想比较一下 但是我不知道如何。

如何使用JavaScript比较以不同角度以不同方向旋转的两个图像?

我可以比较颜色吗?

西古萨

假设两个图像均为矩形,并且旋转均未对其进行裁剪,则可以在画布中循环遍历所有像素,以确定最上方,下方,左侧和右侧的像素(*),然后从此处将其旋转到只能“正确旋转”或上下颠倒(或者,对于正方形,是向左或向右90°),这样就可以减少检查的次数。
从那里开始,您可以从另一张图像中“减去”一张图像,并检查差异是否接近零。

(*):从理论上讲,两个角就足够了,但是更多的角有助于提高精度,因为我们正在处理近似值(因为有浮点数)。

var canvas = [];
var ctx = [];
for(var i = 1; i <= 7; i++)
{
    canvas[i] = document.getElementById('canvas' + i);
    ctx[i] = canvas[i].getContext('2d');
    ctx[i].translate(250, 250);
}
var img = new Image();
var result = document.getElementById('result');

var diffCanvases = function(c1, c2)
{
    var other = c2.getImageData(0, 0, 500, 500).data;
    return c1.getImageData(0, 0, 500, 500).data.map(function(val, i)
    {
        return Math.abs(val - other[i]);
    }).reduce(function(previous, current)
    {
        return previous + current;
    });
};

var drawRotatedImage = function()
{
    var angle1 = Math.random() * 2 * Math.PI;
    var angle2 = Math.random() * 2 * Math.PI;
    ctx[1].rotate(angle1);
    ctx[2].rotate(angle2);
    ctx[1].drawImage(img, -200, -150);
    ctx[2].drawImage(img, -200, -150);
}

var undoRotation = function()
{
    var data = [ctx[1].getImageData(0, 0, 500, 500).data, ctx[2].getImageData(0, 0, 500, 500).data];
    var extremes = [{}, {}];
    for(var i = 0; i < 2; i++)
    {
        top:
        for(var y = 0; y < 500; y++)
        {
            for(var x = 0; x < 500; x++)
            {
                if(data[i][(y * 500 + x) * 4] + data[i][(y * 500 + x) * 4 + 1] + data[i][(y * 500 + x) * 4 + 2] + data[i][(y * 500 + x) * 4 + 3] > 0)
                {
                    extremes[i].top = {x: x, y: y};
                    break top;
                }
            }
        }
        bottom:
        for(var y = 499; y >= 0; y--)
        {
            for(var x = 499; x >= 0; x--)
            {
                if(data[i][(y * 500 + x) * 4] + data[i][(y * 500 + x) * 4 + 1] + data[i][(y * 500 + x) * 4 + 2] + data[i][(y * 500 + x) * 4 + 3] > 0)
                {
                    extremes[i].bottom = {x: x, y: y};
                    break bottom;
                }
            }
        }
        left:
        for(var x = 0; x < 500; x++)
        {
            for(var y = 0; y < 500; y++)
            {
                if(data[i][(y * 500 + x) * 4] + data[i][(y * 500 + x) * 4 + 1] + data[i][(y * 500 + x) * 4 + 2] + data[i][(y * 500 + x) * 4 + 3] > 0)
                {
                    extremes[i].left = {x: x, y: y};
                    break left;
                }
            }
        }
        right:
        for(var x = 499; x >= 0; x--)
        {
            for(var y = 499; y >= 0; y--)
            {
                if(data[i][(y * 500 + x) * 4] + data[i][(y * 500 + x) * 4 + 1] + data[i][(y * 500 + x) * 4 + 2] + data[i][(y * 500 + x) * 4 + 3] > 0)
                {
                    extremes[i].right = {x: x, y: y};
                    break right;
                }
            }
        }
    }
    var angles = [];
    for(var i = 0; i < 2; i++)
    {
        // Diagonals yield the highest accuracy
        var topBottom = Math.atan((extremes[i].bottom.y - extremes[i].top.y) / (extremes[i].bottom.x - extremes[i].top.x));
        var leftRight = Math.atan((extremes[i].left.y - extremes[i].right.y) / (extremes[i].left.x - extremes[i].right.x));
        angles.push(((topBottom + leftRight + Math.PI) / 2) % (Math.PI / 2));
    }
    ctx[3].rotate(-angles[0]);
    ctx[3].drawImage(canvas[1], -250, -250);
    for(var i = 0; i < 4; i++)
    {
        ctx[4 + i].rotate(-angles[1] + Math.PI * i / 2);
        ctx[4 + i].drawImage(canvas[2], -250, -250);
    }
    result.textContent = 'Canvas 3 vs 4: ' + diffCanvases(ctx[3], ctx[4]) + '\n' +
                         'Canvas 3 vs 5: ' + diffCanvases(ctx[3], ctx[5]) + '\n' +
                         'Canvas 3 vs 6: ' + diffCanvases(ctx[3], ctx[6]) + '\n' +
                         'Canvas 3 vs 7: ' + diffCanvases(ctx[3], ctx[7]) + '\n';
}

img.addEventListener('load', function()
{
    drawRotatedImage();
    undoRotation();
});
img.crossOrigin = '';
img.src = 'https://i.imgur.com/o2scuuY.jpg';
canvas
{
    border: solid 1px #999;
    display: block;
}
#result
{
    white-space: pre;
}
Original canvases:
<canvas id="canvas1" width="500" height="500"></canvas>
<canvas id="canvas2" width="500" height="500"></canvas>
Canvas 1 "fixed":
<canvas id="canvas3" width="500" height="500"></canvas>
All options for canvas 2 "fixed":
<canvas id="canvas4" width="500" height="500"></canvas>
<canvas id="canvas5" width="500" height="500"></canvas>
<canvas id="canvas6" width="500" height="500"></canvas>
<canvas id="canvas7" width="500" height="500"></canvas>
<div id="result"></div>

在此版本中,单个像素偏移将已经产生巨大的变化。通过检测所有“固定”图像的顶部和左侧偏移量,将第一幅画布与其他四个画布的顶部和左侧偏移进行比较,并调整图像以使差异均匀,可以轻松地将其最小化。
但是我今天对画布和图像已经一无所知。

示例图像取自LoremPixel

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章