使用javascript比较旋转图像
Compare rotated images using 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);
}
在上面的代码中,我正在迭代图像。我给出样本图像在 samplcanvas 和canvas1是我画我的图像列表。然后我要比较它们。但我不知道怎么做。
我怎么能比较两个图像在不同的方向旋转在随机角度使用JavaScript?
我可以比较颜色吗?
假设这两个图像都是矩形,并且旋转确实没有裁剪它们,您可以循环画布中的所有像素以确定最上、最下、最左和最右像素(*),并从那里您可以将其旋转到一个位置,它只能"正确旋转"或颠倒(或者,对于正方形,向左或向右90°),让您检查更少的情况。从那里,你可以从另一个图像中"减去"一个图像,并检查差异是否接近于零。
(*):理论上,两个角就足够了,但更多的角有助于提高精度,因为我们处理的是近似值(因为float)。
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的示例图像。
"Same"就像…真的,但是真的一样吗?几乎不可能的。
一旦图像被旋转,可能是裁剪,修剪等(你错过了解释什么是边缘情况,并显示一些代码)。
只是给你一个想法如何处理这个问题:
- 我将这两个图像转换为B/W(得到0个零白色和1个黑色数据)
- 去除噪声(滤波/清洗隔离的
"1"(black)
像素数据) - 重叠图像并从0-359度的步骤旋转一个
- 在每一步(旋转)过程中,平均排除算法(基本上1-1=0)
- 然后逐块处理整个合并结果
所以基本上如果合并的结果是一个几乎完全白色的(大部分是"0")结果-
你有与。
如果你不知道旋转角度,这是计算机视觉中一个经典的图像匹配案例。
图像匹配计算量大,不适合web应用程序。
我会尝试找到一种方法来计算旋转角度,并在比较之前将图像旋转回来。如果没有其他方法,我会使用opencv或类似的库实现图像匹配rest api。
编辑
为了访问画布像素数据,使用getImageData
函数
- 需要关于随机图像旋转的指南
- Jquery CSS背景图像旋转
- 全屏背景图像+旋转图像
- 随机图像旋转的多个实例
- JS下拉菜单显示在图像旋转器上
- 请解释Javascript图像旋转代码
- JavaScript 中的图像旋转器(键下)
- jquery 图像旋转器(仅在 JS 中传递图像)
- 如何停止多次单击下一个以破坏我的图像旋转器
- 停止 3 个图像旋转只需单击一个按钮
- 背景图像旋转器.php + jQuery每4秒显示一次随机照片
- 图像旋转背景 js 跳转到页面顶部
- 画布图像旋转中的问题
- 在画布上绘制多个图像,每个图像旋转
- 使用关键帧图像旋转器时,图像不会在两个块之间同步协调
- 最简单的图像旋转器 - 使用设置间隔失败
- 需要按钮显示/隐藏图像旋转 href 添加到 javascript 代码中
- 图像旋转和Jcrop.js
- 360 度图像旋转指示器
- 通过手机加载时,画布图像会将图像旋转 90 度