有2个256色的BMP图,A大小600*600,B大小100*100,现在想在A中找出和B相似的区域,有什么好的快速的算法吗?

解决方案 »

  1.   

    建立图片金字塔(有点像mip图),搜索多个比较接近的区域,然后再做匹配
      

  2.   

    http://www.mndsoft.com这里有有个例子
      

  3.   

    http://www.mndsoft.com都是vb的例子:(
      

  4.   

    //参考如下代码,多种情况测试通过function FindBitmapPoint( //寻找子位图的位置
      mBitmapMain: TBitmap; //主位图
      mBitmapSub: TBitmap //子位图
    ): TPoint; //返回子图像存在的坐标,如不存在则返回(-1,-1)
    //Zswang 2006-08-04 wjhu111#21cn.com 转贴请别删除,尊重作者才能让其有兴趣公开文档
    const
    //pfDevice, pf1bit, pf4bit, pf8bit, pf15bit, pf16bit, pf24bit, pf32bit, pfCustom
      cBitsPerPixels: array[TPixelFormat] of Byte = (0, 1, 4, 8, 15, 16, 24, 32, 0);
                           //像素格式所占用的字位数列表
    var
      I, J, K, L: Integer; //循环变量
      vStrMain: string; //主位图一行的像素数据字符串格式
      vStrSub: string; //子位图一行的像素数据字符串格式
      vLine: PChar; //临时ScanLine用
      vBytesSub: Integer; //子位图一行像素数据占用的字节数
      vBytesMain: Integer; //主位图一行像素数据占用的字节数
      vBitsPerPixels: Byte; //一个像素占用的字位数
      vFlag: Boolean;
    begin
      Result := Point(-1, -1);
      ///////Begin 安全判断
      if not Assigned(mBitmapMain) or not Assigned(mBitmapSub) then Exit;
      if mBitmapMain.PixelFormat <> mBitmapSub.PixelFormat then Exit;
      if (mBitmapSub.Height <= 0) or (mBitmapSub.Width <= 0) or
        (mBitmapMain.Height <= 0) or (mBitmapMain.Width <= 0) then Exit;
      ///////End 安全判断  vBitsPerPixels := cBitsPerPixels[mBitmapMain.PixelFormat];
      if vBitsPerPixels = 0 then Exit;
      vBytesSub := (mBitmapSub.Width * vBitsPerPixels + 7) div 8;
      vBytesMain := (mBitmapMain.Width * vBitsPerPixels + 7) div 8;
      if (vBytesSub = 0) or (vBytesMain = 0) then Exit;
      SetLength(vStrSub, vBytesSub);
      SetLength(vStrMain, vBytesMain);  vLine := mBitmapSub.ScanLine[0];
      Move(vLine^, vStrSub[1], vBytesSub);
      for I := 0 to mBitmapMain.Height - 1 do
      begin
        vLine := mBitmapMain.ScanLine[I];
        Move(vLine^, vStrMain[1], vBytesMain);
        J := Pos(vStrSub, vStrMain); //寻找子位图第一行是否存在主位图的一行中
        L := J;
        while J > 0 do
        begin
          vFlag := True;
          for K := 1 to mBitmapSub.Height - 1 do
          begin
            if I + K >= mBitmapMain.Height then //边界判断
            begin
              vFlag := False;
              Break;
            end;
            vLine := mBitmapMain.ScanLine[I + K];
            Move(vLine^, vStrMain[1], vBytesMain);
            vLine := mBitmapSub.ScanLine[K];
            Move(vLine^, vStrSub[1], vBytesSub);
            if not CompareMem(@vStrSub[1], @vStrMain[J], vBytesSub) then //判断子位图之后的行以相应主位图是否一致
            begin
              vLine := mBitmapMain.ScanLine[I];
              Move(vLine^, vStrMain[1], vBytesMain);
              vLine := mBitmapSub.ScanLine[0];
              Move(vLine^, vStrSub[1], vBytesSub);
              vFlag := False; //不一致打上标记
              Break;
            end;
          end;
          if vFlag then //一致则返回
          begin
            Result := Point((J - 1) div vBitsPerPixels * 8, I);
                            //计算多少像素位置
            Break;
          end;
          J := Pos(vStrSub, Copy(vStrMain, L + 1, MaxInt)); //考虑子位图第一行在主位图`后面还会出现的情况
          if J > 0 then
          begin
            J := L + J;
            L := J;
          end;
        end;
      end;
    end; { FindBitmapPoint }procedure TForm1.Button1Click(Sender: TObject);
    var
      vPoint: TPoint;
    begin
      Image1.Picture.Bitmap.PixelFormat := pf15bit;
      Image2.Picture.Bitmap.PixelFormat := pf15bit;
      vPoint := FindBitmapPoint(Image1.Picture.Bitmap, Image2.Picture.Bitmap);  ///////Begin 测试输出用
      Caption := Format('%d,%d', [vPoint.X, vPoint.Y]);
      if vPoint.X < 0 then Exit;
      Bevel1.Width := Image2.Picture.Bitmap.Width;
      Bevel1.Height := Image2.Picture.Bitmap.Height;
      Bevel1.Left := Image1.Left + vPoint.X;
      Bevel1.Top := Image1.Top + vPoint.Y;
      ///////End 测试输出用
    end;
      

  5.   

    Image1.Picture.Bitmap.PixelFormat := pf15bit;
      Image2.Picture.Bitmap.PixelFormat := pf15bit;
    删除
      

  6.   

    把子图的一行(或一个比较短的像素段)提取出来做样本,直接在大图当中找完全匹配,
    匹配后,获取匹配位置,再进行全图比较或者抽样比较。不同就继续寻找下一个匹配。
    选择好适当的样本长度是关键。
    完全比较直接xor,查零。
      

  7.   

    to DelphiGuy
    应该可以, 你只需要建立不同的的比对函数,例如色调不同,就都转化成灰度;不同亮度间可以匹配对比度;如果不要求图案完全一样,还可以给出一定的匹配度等等等