2012-07-05 45 views
3

我想编写一个获取2位图(小图像和大图像)的函数。 它应该搜索大图像中小的位置。然后它应该返回子图像所在的(X/Y)点。在C中查找放大图像中的子图像#

我已经找到了一堆的解决方案,但都被用Java编写的,比如这一个:Find known sub image in larger image 于是,我就重新编程在C#中,但我总是失败,因为代码是不是真正的Java。 Image.getPixel(x,y)方法在那里不存在,我不知道阈值应该是多少。

+0

为什么要标记java? – 2012-07-05 11:55:39

+0

因为我找到了java代码并找不到这些方法。 所以我需要某人帮忙。 – lui1000 2012-07-05 12:35:26

回答

6

你走了。该函数返回在larg图像中找到的所有位置,因为小图像也可能包含在大图像中多次。如果你愿意,你可以重写功能不安全的更多的性能。

public static List<Point> GetSubPositions(Bitmap main, Bitmap sub) { 
    List<Point> possiblepos = new List<Point>(); 

    int mainwidth = main.Width; 
    int mainheight = main.Height; 

    int subwidth = sub.Width; 
    int subheight = sub.Height; 

    int movewidth = mainwidth - subwidth; 
    int moveheight = mainheight - subheight; 

    BitmapData bmMainData = main.LockBits(new Rectangle(0, 0, mainwidth, mainheight), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb); 
    BitmapData bmSubData = sub.LockBits(new Rectangle(0, 0, subwidth, subheight), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb); 

    int bytesMain = Math.Abs(bmMainData.Stride) * mainheight; 
    int strideMain = bmMainData.Stride; 
    System.IntPtr Scan0Main = bmMainData.Scan0; 
    byte[] dataMain = new byte[bytesMain]; 
    System.Runtime.InteropServices.Marshal.Copy(Scan0Main, dataMain, 0, bytesMain); 

    int bytesSub = Math.Abs(bmSubData.Stride) * subheight; 
    int strideSub = bmSubData.Stride; 
    System.IntPtr Scan0Sub = bmSubData.Scan0; 
    byte[] dataSub = new byte[bytesSub]; 
    System.Runtime.InteropServices.Marshal.Copy(Scan0Sub, dataSub, 0, bytesSub); 

    for (int y = 0; y < moveheight; ++y) { 
     for (int x = 0; x < movewidth; ++x) { 
      MyColor curcolor = GetColor(x, y, strideMain, dataMain); 

      foreach (var item in possiblepos.ToArray()) { 
       int xsub = x - item.X; 
       int ysub = y - item.Y; 
       if (xsub >= subwidth || ysub >= subheight || xsub < 0) 
        continue; 

       MyColor subcolor = GetColor(xsub, ysub, strideSub, dataSub); 

       if (!curcolor.Equals(subcolor)) { 
        possiblepos.Remove(item); 
       } 
      } 

      if (curcolor.Equals(GetColor(0, 0, strideSub, dataSub))) 
       possiblepos.Add(new Point(x, y)); 
     } 
    } 

    System.Runtime.InteropServices.Marshal.Copy(dataSub, 0, Scan0Sub, bytesSub); 
    sub.UnlockBits(bmSubData); 

    System.Runtime.InteropServices.Marshal.Copy(dataMain, 0, Scan0Main, bytesMain); 
    main.UnlockBits(bmMainData); 

    return possiblepos; 
} 

private static MyColor GetColor(Point point, int stride, byte[] data) { 
    return GetColor(point.X, point.Y, stride, data); 
} 

private static MyColor GetColor(int x, int y, int stride, byte[] data) { 
    int pos = y * stride + x * 4; 
    byte a = data[pos + 3]; 
    byte r = data[pos + 2]; 
    byte g = data[pos + 1]; 
    byte b = data[pos + 0]; 
    return MyColor.FromARGB(a, r, g, b); 
} 

struct MyColor { 
    byte A; 
    byte R; 
    byte G; 
    byte B; 

    public static MyColor FromARGB(byte a, byte r, byte g, byte b) { 
     MyColor mc = new MyColor(); 
     mc.A = a; 
     mc.R = r; 
     mc.G = g; 
     mc.B = b; 
     return mc; 
    } 

    public override bool Equals(object obj) { 
     if (!(obj is MyColor)) 
      return false; 
     MyColor color = (MyColor)obj; 
     if(color.A == this.A && color.R == this.R && color.G == this.G && color.B == this.B) 
      return true; 
     return false; 
    } 
} 
+0

哇!非常感谢! – lui1000 2012-07-05 14:37:15