有一个目录中有jpg文件,一个jpg文件应该与目录中的文件进行比较,这样就可以找到2个图形相同的文件。这是最简单的方法。也许可以比较R,G,B(可变性)的差异,而不是R,G,B值本身,因为它们可能会随着不同程度的jpeg压缩而略有不同。
hfyxw5xn1#
用于比较2个图像:1.将两个jpg加载到内存中的位图中参见opening image file on c++ , PNG , JPEG的简单C++ Builder的例子只是移植到pascal的类名和用法应该是相同的 Delphi 。1.计算绝对差值使用Graphics::TBitmap::ScanLine[y]用于快速像素访问,使用并集或字节指向用于单个颜色通道访问,并且对于每个颜色通道分别计算绝对平均差和最大绝对差。有关详细信息,请参见TBitmap and ScanLine[y] usage和color channel access example然而,正如SilverWarior所指出的,使用RGB空间对此并不好,所以要在亮度上进行比较(只需将RGB转换为亮度)1.结果阈值简单地说,如果MAX和AVG差值中的任何一个大于某个阈值,则两个图像不相同。要创建文件列表,可以使用winapi FindFirst,FindNext,FindClose获取目录列表,也可以使用win3.11 VCL组件中的文件列表,设置其目录并以列表形式获取文件...然后自动比较图像...下面是比较2个图像的小C++构建器示例:
Graphics::TBitmap::ScanLine[y]
TBitmap
ScanLine[y]
FindFirst,FindNext,FindClose
//$$---- 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也不安全。
picture_compare
pf32bit
picture_load
1条答案
按热度按时间hfyxw5xn1#
用于比较2个图像:
1.将两个jpg加载到内存中的位图中
参见opening image file on c++ , PNG , JPEG的简单C++ Builder的例子只是移植到pascal的类名和用法应该是相同的 Delphi 。
1.计算绝对差值
使用
Graphics::TBitmap::ScanLine[y]
用于快速像素访问,使用并集或字节指向用于单个颜色通道访问,并且对于每个颜色通道分别计算绝对平均差和最大绝对差。有关详细信息,请参见
TBitmap
andScanLine[y]
usage和color channel access example然而,正如SilverWarior所指出的,使用RGB空间对此并不好,所以要在亮度上进行比较(只需将RGB转换为亮度)
1.结果阈值
简单地说,如果MAX和AVG差值中的任何一个大于某个阈值,则两个图像不相同。
要创建文件列表,可以使用winapi
FindFirst,FindNext,FindClose
获取目录列表,也可以使用win3.11 VCL组件中的文件列表,设置其目录并以列表形式获取文件...然后自动比较图像...
下面是比较2个图像的小C++构建器示例:
你应该玩的阈值(我选择的形式非常小的输入样本),以满足您的需要,也要注意,这是比较作为灰度图像,所以你应该添加一些颜色比较太(集成一些地区到平均颜色和比较)
函数
picture_compare
返回真为“相同”的图像...注意,它期望pf32bit
像素格式为两个图像!!!不同的格式将改变像素访问,也可能改变RGB顺序,这将导致错误的权重转换为亮度/灰度。像素格式是在picture_load
期间设置的,所以不要忘记设置它,如果你使用不同的加载方法...同样为了比较颜色,你可以为每个颜色通道分别做一个直方图,然后比较...
我使用double来防止avgdif的(32位)整数溢出,但要记住,对于高分辨率,即使是double也不安全。