Android 中的图像比较。
Image Comparison in Android.
我是 Android 学习者。我正在尝试图像比较。它显示不同大小的相同图像的图像不相同,因此我使用 createScaledBitmap(Bitmap src, int dstWidth, int dstHeight, boolean filter) 重新缩放了图像。即使在重新缩放之后,当我比较我得到的结果时,两个图像都是不同的。请帮帮我。
bmpimg1 = BitmapFactory.decodeFile(path1);
bmpimg2 = BitmapFactory.decodeFile(path2);
int bm1Height = bmpimg1.getHeight();
int bm1Width = bmpimg1.getWidth();
int bm1Res = bm1Height * bm1Width;
int bm2Height = bmpimg2.getHeight();
int bm2Width = bmpimg2.getWidth();
int bm2Res = bm2Height * bm2Width;
if(bm1Res==bm2Res){
Toast.makeText(getApplicationContext(), "Both Images Same Size", Toast.LENGTH_SHORT).show();
if(bmpimg1.sameAs(bmpimg2)){
Toast.makeText(getApplicationContext(), "Same", Toast.LENGTH_LONG).show();
}else{
Toast.makeText(getApplicationContext(), "Not Same", Toast.LENGTH_LONG).show();
}
}
if (bm1Res > bm2Res)
{
Bitmap rbm1 = Bitmap.createScaledBitmap(bmpimg1, bmpimg2.getWidth(), bmpimg2.getHeight(), true);
ImageView imageView1 = (ImageView) findViewById(R.id.image1);
imageView1.setImageBitmap(rbm1);
Toast.makeText(getApplicationContext(), "Image1 has to be Scaled", Toast.LENGTH_SHORT).show();
if(rbm1.sameAs(bmpimg2)){
Toast.makeText(getApplicationContext(), "Same", Toast.LENGTH_LONG).show();
}else{
Toast.makeText(getApplicationContext(), "Not Same", Toast.LENGTH_LONG).show();
}
}
if(bm1Res<bm2Res)
{
Bitmap rbm2 = Bitmap.createScaledBitmap(bmpimg2, bmpimg1.getWidth(), bmpimg1.getHeight(), true);
ImageView imageView2 = (ImageView) findViewById(R.id.image2);
imageView2.setImageBitmap(rbm2);
Toast.makeText(getApplicationContext(), "Image2 has to be Scaled", Toast.LENGTH_SHORT).show();
if(bmpimg1.sameAs(rbm2)) {
Toast.makeText(getApplicationContext(), "Same", Toast.LENGTH_LONG).show();
}else{
Toast.makeText(getApplicationContext(), "Not Same", Toast.LENGTH_LONG).show();
}
}
更新答案
为了回答您评论中的问题,有多种方法 - 这取决于您实际想要实现的目标......例如,您是否需要检测相对于彼此旋转的图像,或者模糊、平滑或篡改。有些方法是...
感知散列 - 您为所有图像创建散列并计算图像之间的距离。请参阅 here 以及关于 pHash
的评论。
平均颜色 - 您计算图像的平均(或平均)颜色并比较平均值 - 这种方法非常简单。
RMSE 或类似的 - 您计算所有像素的均方根误差并寻找低值以指示图像相似。使用 ImageMagick 可以轻松完成此方法和上述所有方法。查看并投票支持 Kurt (@KurtPfeifle) 出色而详尽的回答 。
特征 - 您在图像中找到形状和特征并进行比较 - 尝试谷歌搜索 "SIFT"
.
原答案
不是你代码的问题,是信息丢失的根本问题。如果将图像缩小到较小的尺寸,通常会丢失信息,因为较小的图像不能包含与较大图像相同的信息量。有很多事情可能会发生...
掉色
假设您有一张可爱的 1000x1000 大图片,具有平滑的渐变和相应的数百万种颜色,如下所示:
如果您现在将它的大小调整为 32x32 的图像,它现在最多只能包含 1,024 种颜色,因此当您再次调整它的大小时,您可能会得到这样的结果:
现在您可以看到出现了条带 - 颜色聚集在一起形成较小图像可以容纳的较少数量的颜色。
格式
当您调整图像大小时,执行此操作的程序可能会从每像素 24 位的真彩色图像变为只有 256 种或更少颜色的调色图像。图像可能看起来相同,但不一定完全相同。
同样与格式有关,您可以调整图像大小并使用不同的图像格式,该格式不能包含原始图像的所有特征,之后再次调整大小时它们将丢失。例如,您的原始图像可能是具有透明度的 PNG
,您可能已将其缩小为不能包含透明度的 JPEG
,然后再重新调整为 PNG
,并且它会丢失。
Resolution/Detail
如果您的图像中有一些清晰的文字或细节,它们可能会丢失。假设你从这个开始:
然后缩小尺寸然后再备份,你可能会得到这个,因为较小的图像无法容纳细节。同样,这意味着您的比较将无法发现它们是同一张图片。
同样使用简单的线条..
缩小并重新放大
我是 Android 学习者。我正在尝试图像比较。它显示不同大小的相同图像的图像不相同,因此我使用 createScaledBitmap(Bitmap src, int dstWidth, int dstHeight, boolean filter) 重新缩放了图像。即使在重新缩放之后,当我比较我得到的结果时,两个图像都是不同的。请帮帮我。
bmpimg1 = BitmapFactory.decodeFile(path1);
bmpimg2 = BitmapFactory.decodeFile(path2);
int bm1Height = bmpimg1.getHeight();
int bm1Width = bmpimg1.getWidth();
int bm1Res = bm1Height * bm1Width;
int bm2Height = bmpimg2.getHeight();
int bm2Width = bmpimg2.getWidth();
int bm2Res = bm2Height * bm2Width;
if(bm1Res==bm2Res){
Toast.makeText(getApplicationContext(), "Both Images Same Size", Toast.LENGTH_SHORT).show();
if(bmpimg1.sameAs(bmpimg2)){
Toast.makeText(getApplicationContext(), "Same", Toast.LENGTH_LONG).show();
}else{
Toast.makeText(getApplicationContext(), "Not Same", Toast.LENGTH_LONG).show();
}
}
if (bm1Res > bm2Res)
{
Bitmap rbm1 = Bitmap.createScaledBitmap(bmpimg1, bmpimg2.getWidth(), bmpimg2.getHeight(), true);
ImageView imageView1 = (ImageView) findViewById(R.id.image1);
imageView1.setImageBitmap(rbm1);
Toast.makeText(getApplicationContext(), "Image1 has to be Scaled", Toast.LENGTH_SHORT).show();
if(rbm1.sameAs(bmpimg2)){
Toast.makeText(getApplicationContext(), "Same", Toast.LENGTH_LONG).show();
}else{
Toast.makeText(getApplicationContext(), "Not Same", Toast.LENGTH_LONG).show();
}
}
if(bm1Res<bm2Res)
{
Bitmap rbm2 = Bitmap.createScaledBitmap(bmpimg2, bmpimg1.getWidth(), bmpimg1.getHeight(), true);
ImageView imageView2 = (ImageView) findViewById(R.id.image2);
imageView2.setImageBitmap(rbm2);
Toast.makeText(getApplicationContext(), "Image2 has to be Scaled", Toast.LENGTH_SHORT).show();
if(bmpimg1.sameAs(rbm2)) {
Toast.makeText(getApplicationContext(), "Same", Toast.LENGTH_LONG).show();
}else{
Toast.makeText(getApplicationContext(), "Not Same", Toast.LENGTH_LONG).show();
}
}
更新答案
为了回答您评论中的问题,有多种方法 - 这取决于您实际想要实现的目标......例如,您是否需要检测相对于彼此旋转的图像,或者模糊、平滑或篡改。有些方法是...
感知散列 - 您为所有图像创建散列并计算图像之间的距离。请参阅 here 以及关于 pHash
的评论。
平均颜色 - 您计算图像的平均(或平均)颜色并比较平均值 - 这种方法非常简单。
RMSE 或类似的 - 您计算所有像素的均方根误差并寻找低值以指示图像相似。使用 ImageMagick 可以轻松完成此方法和上述所有方法。查看并投票支持 Kurt (@KurtPfeifle) 出色而详尽的回答
特征 - 您在图像中找到形状和特征并进行比较 - 尝试谷歌搜索 "SIFT"
.
原答案
不是你代码的问题,是信息丢失的根本问题。如果将图像缩小到较小的尺寸,通常会丢失信息,因为较小的图像不能包含与较大图像相同的信息量。有很多事情可能会发生...
掉色
假设您有一张可爱的 1000x1000 大图片,具有平滑的渐变和相应的数百万种颜色,如下所示:
如果您现在将它的大小调整为 32x32 的图像,它现在最多只能包含 1,024 种颜色,因此当您再次调整它的大小时,您可能会得到这样的结果:
现在您可以看到出现了条带 - 颜色聚集在一起形成较小图像可以容纳的较少数量的颜色。
格式
当您调整图像大小时,执行此操作的程序可能会从每像素 24 位的真彩色图像变为只有 256 种或更少颜色的调色图像。图像可能看起来相同,但不一定完全相同。
同样与格式有关,您可以调整图像大小并使用不同的图像格式,该格式不能包含原始图像的所有特征,之后再次调整大小时它们将丢失。例如,您的原始图像可能是具有透明度的 PNG
,您可能已将其缩小为不能包含透明度的 JPEG
,然后再重新调整为 PNG
,并且它会丢失。
Resolution/Detail
如果您的图像中有一些清晰的文字或细节,它们可能会丢失。假设你从这个开始:
然后缩小尺寸然后再备份,你可能会得到这个,因为较小的图像无法容纳细节。同样,这意味着您的比较将无法发现它们是同一张图片。
同样使用简单的线条..
缩小并重新放大