delphi 比较两个相同的jpg文件与不同的压缩比

5n0oy7gb  于 2023-02-04  发布在  其他
关注(0)|答案(1)|浏览(156)

有一个目录中有jpg文件,一个jpg文件应该与目录中的文件进行比较,这样就可以找到2个图形相同的文件。这是最简单的方法。也许可以比较R,G,B(可变性)的差异,而不是R,G,B值本身,因为它们可能会随着不同程度的jpeg压缩而略有不同。

hfyxw5xn

hfyxw5xn1#

用于比较2个图像:
1.将两个jpg加载到内存中的位图中
参见opening image file on c++ , PNG , JPEG的简单C++ Builder的例子只是移植到pascal的类名和用法应该是相同的 Delphi 。
1.计算绝对差值
使用Graphics::TBitmap::ScanLine[y]用于快速像素访问,使用并集或字节指向用于单个颜色通道访问,并且对于每个颜色通道分别计算绝对平均差最大绝对差
有关详细信息,请参见TBitmap and ScanLine[y] usagecolor channel access example
然而,正如SilverWarior所指出的,使用RGB空间对此并不好,所以要在亮度上进行比较(只需将RGB转换为亮度)
1.结果阈值
简单地说,如果MAX和AVG差值中的任何一个大于某个阈值,则两个图像不相同。
要创建文件列表,可以使用winapi FindFirst,FindNext,FindClose获取目录列表,也可以使用win3.11 VCL组件中的文件列表,设置其目录并以列表形式获取文件...
然后自动比较图像...
下面是比较2个图像的小C++构建器示例:

//$$---- Form CPP ----
//---------------------------------------------------------------------------
#include <vcl.h>
#include <math.h>
#include <jpeg.hpp>
#pragma hdrstop
#include "win_main.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TMain *Main;
Graphics::TBitmap *bmp0,*bmp1;
//---------------------------------------------------------------------------
int picture_load(Graphics::TBitmap *bmp,AnsiString name)
    {
    if (bmp==NULL) return 0;
    if (!FileExists(name)) return 0;
    bmp->HandleType=bmDIB;
    bmp->PixelFormat=pf32bit;
    AnsiString ext=ExtractFileExt(name).LowerCase();
    for(;;)
        {
        if (ext==".bmp")
            {
            bmp->LoadFromFile(name);
            break;
            }
        if (ext==".jpg")
            {
            TJPEGImage *jpg=new TJPEGImage;
            if (jpg==NULL) return 0;
            jpg->LoadFromFile(name);
            bmp->Assign(jpg);
            delete jpg;
            break;
            }
        return 0;
        }
    bmp->HandleType=bmDIB;
    bmp->PixelFormat=pf32bit;
    return 1;
    }
//---------------------------------------------------------------------------
int picture_compare(Graphics::TBitmap *bmp0,Graphics::TBitmap *bmp1)
    {
    if ((bmp0==NULL)&&(bmp1==NULL)) return 1;
    if (bmp0==NULL) return 0;
    if (bmp1==NULL) return 0;
    if (bmp0->Width !=bmp1->Width ) return 0;
    if (bmp0->Height!=bmp1->Height) return 0;
    int x,y,a;
    double c0,c1,dc,de,maxdif=0.0,avgdif=0.0;
    BYTE *p0,*p1;
    for (y=0;y<bmp0->Height;y++)
        {
        p0=(BYTE*)bmp0->ScanLine[y];
        p1=(BYTE*)bmp1->ScanLine[y];
        for (a=0,x=0;x<bmp0->Width;x++)
            {
            c0 =p0[a]; c1 =p1[a]; a++; c0*=0.0722; c1*=0.0722;  // B
            c0+=p0[a]; c1+=p1[a]; a++; c0*=0.7152; c1*=0.7152;  // G
            c0+=p0[a]; c1+=p1[a]; a++; c0*=0.2126; c1*=0.2126;  // R
                                  a++;                          // A
            dc=fabs(c0-c1);if (maxdif<dc) maxdif=dc; avgdif+=dc;
            }
        }
    avgdif/=bmp0->Width;
    avgdif/=bmp0->Height;
    if (avgdif>10) return 0;
    if (maxdif>50) return 0;
    return 1;
    }
//---------------------------------------------------------------------------
__fastcall TMain::TMain(TComponent* Owner) : TForm(Owner)
    {
    bmp0=new Graphics::TBitmap;
    bmp1=new Graphics::TBitmap;

    picture_load(bmp0,"in0.jpg");
    picture_load(bmp1,"in1.jpg");
    Caption=picture_compare(bmp0,bmp1);

    int xs,ys;
    xs=bmp0->Width+bmp1->Width;
    ys=bmp0->Height;
    if (ys<bmp1->Height) ys=bmp1->Height;
    ClientWidth=xs;
    ClientHeight=ys;
    }
//---------------------------------------------------------------------------
void __fastcall TMain::FormDestroy(TObject *Sender)
    {
    if (bmp0) delete bmp0; bmp0=NULL;
    if (bmp1) delete bmp1; bmp1=NULL;
    }
//---------------------------------------------------------------------------
void __fastcall TMain::FormPaint(TObject *Sender)
    {
    Canvas->Draw(0,0,bmp0);
    Canvas->Draw(bmp0->Width,0,bmp1);
    }
//---------------------------------------------------------------------------

你应该玩的阈值(我选择的形式非常小的输入样本),以满足您的需要,也要注意,这是比较作为灰度图像,所以你应该添加一些颜色比较太(集成一些地区到平均颜色和比较)
函数picture_compare返回真为“相同”的图像...注意,它期望pf32bit像素格式为两个图像!!!不同的格式将改变像素访问,也可能改变RGB顺序,这将导致错误的权重转换为亮度/灰度。像素格式是在picture_load期间设置的,所以不要忘记设置它,如果你使用不同的加载方法...
同样为了比较颜色,你可以为每个颜色通道分别做一个直方图,然后比较...
我使用double来防止avgdif的(32位)整数溢出,但要记住,对于高分辨率,即使是double也不安全。

相关问题