-
Member
[C#] [Source] Find image in image
hi,
for those who dont know how to find the position of an image in an image.
Hope this helps.
UPDATE: added BITLOCK, some other speed improvements and code infos. (it was pooring in the train =))
greets
Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Drawing;
namespace D3_Bot_Tool
{
class LockedFastImage
{
private Bitmap image;
private byte[] rgbValues;
private System.Drawing.Imaging.BitmapData bmpData;
private IntPtr ptr;
private int bytes;
public LockedFastImage(Bitmap image)
{
this.image = image;
Rectangle rect = new Rectangle(0, 0, image.Width, image.Height);
bmpData = image.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, image.PixelFormat);
ptr = bmpData.Scan0;
bytes = Math.Abs(bmpData.Stride) * image.Height;
rgbValues = new byte[bytes];
System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, bytes);
}
~LockedFastImage()
{
// Try to unlock the bits. Who cares if it dont work...
try
{
image.UnlockBits(bmpData);
}
catch { }
}
/// <summary>
/// Returns or sets a pixel of the image.
/// </summary>
/// <param name="x">x parameter of the pixel</param>
/// <param name="y">y parameter of the pixel</param>
public Color this[int x, int y]
{
get
{
int index = (x + (y * image.Width)) * 4;
return Color.FromArgb(rgbValues[index + 3], rgbValues[index + 2], rgbValues[index + 1], rgbValues[index]);
}
set
{
int index = (x + (y * image.Width)) * 4;
rgbValues[index] = value.B;
rgbValues[index + 1] = value.G;
rgbValues[index + 2] = value.R;
rgbValues[index + 3] = value.A;
}
}
/// <summary>
/// Width of the image.
/// </summary>
public int Width
{
get
{
return image.Width;
}
}
/// <summary>
/// Height of the image.
/// </summary>
public int Height
{
get
{
return image.Height;
}
}
/// <summary>
/// Returns the modified Bitmap.
/// </summary>
public Bitmap asBitmap()
{
System.Runtime.InteropServices.Marshal.Copy(rgbValues, 0, ptr, bytes);
return image;
}
}
class ImageChecker
{
private LockedFastImage big_image;
private LockedFastImage small_image;
/// <summary>
/// The time needed for last operation.
/// </summary>
public TimeSpan time_needed = new TimeSpan();
/// <summary>
/// Error return value.
/// </summary>
static public Point CHECKFAILED = new Point(-1, -1);
/// <summary>
/// Constructor of the ImageChecker
/// </summary>
/// <param name="big_image">The image containing the small image.</param>
/// <param name="small_image">The image located in the big image.</param>
public ImageChecker(Bitmap big_image, Bitmap small_image)
{
this.big_image = new LockedFastImage(big_image);
this.small_image = new LockedFastImage(small_image);
}
/// <summary>
/// Returns the location of the small image in the big image. Returns CHECKFAILED if not found.
/// </summary>
/// <param name="x_speedUp">speeding up at x achsis.</param>
/// <param name="y_speedUp">speeding up at y achsis.</param>
/// <param name="begin_percent_x">Reduces the search rect. 0 - 100</param>
/// <param name="end_percent_x">Reduces the search rect. 0 - 100</param>
/// <param name="begin_percent_x">Reduces the search rect. 0 - 100</param>
/// <param name="end_percent_y">Reduces the search rect. 0 - 100</param>
public Point bigContainsSmall(int x_speedUp = 1, int y_speedUp = 1, int begin_percent_x = 0, int end_percent_x = 100, int begin_percent_y = 0, int end_percent_y = 100)
{
/*
* SPEEDUP PARAMETER
* It might be enough to check each second or third pixel in the small picture.
* However... In most cases it would be enough to check 4 pixels of the small image for diablo porposes.
* */
/*
* BEGIN, END PARAMETER
* In most cases we know where the image is located, for this we have the begin and end paramenters.
* */
DateTime begin = DateTime.Now;
if (x_speedUp < 1) x_speedUp = 1;
if (y_speedUp < 1) y_speedUp = 1;
if (begin_percent_x < 0 || begin_percent_x > 100) begin_percent_x = 0;
if (begin_percent_y < 0 || begin_percent_y > 100) begin_percent_y = 0;
if (end_percent_x < 0 || end_percent_x > 100) end_percent_x = 100;
if (end_percent_y < 0 || end_percent_y > 100) end_percent_y = 100;
int x_start = (int)((double)big_image.Width * ((double)begin_percent_x / 100.0));
int x_end = (int)((double)big_image.Width * ((double)end_percent_x / 100.0));
int y_start = (int)((double)big_image.Height * ((double)begin_percent_y / 100.0));
int y_end = (int)((double)big_image.Height * ((double)end_percent_y / 100.0));
/*
* We cant speed up the big picture, because then we have to check pixels in the small picture equal to the speeded up size
* for each pixel in the big picture.
* Would give no speed improvement.
* */
//+ 1 because first pixel is in picture. - small because image have to be fully in the other image
for (int x = x_start; x < x_end - small_image.Width + 1; x++)
for (int y = y_start; y < y_end - small_image.Height + 1; y++)
{
//now we check if all pixels matches
for (int sx = 0; sx < small_image.Width; sx += x_speedUp)
for (int sy = 0; sy < small_image.Height; sy += y_speedUp)
{
if (small_image[sx, sy] != big_image[x + sx, y + sy])
goto CheckFailed;
}
//check ok
time_needed = DateTime.Now - begin;
return new Point(x, y);
CheckFailed: ;
}
time_needed = DateTime.Now - begin;
return CHECKFAILED;
}
}
}
Last edited by Shoruun; 06-26-2012 at 12:42 PM.
-
Post Thanks / Like - 1 Thanks
Berdar (1 members gave Thanks to Shoruun for this useful post)
-
Sergeant
-
Member
Due to +Rep there is an update of the code =)
btw... how do i give rep? did not found a button for it :/
-
Member
I was pinging google on this problem. It has been a while since I have logged into this site.
Anyway your code popped up in google and so I read through it to understand what was going on before running it. I have since adjusted the Color property to handle 8,16,24,32,and 64 bitmaps. That was a fun exercise since I did not know to much about bitmaps and such. Anyway back on point.
Testing the code I took a (Win7) snip of the game screen and then another snip of a smaller section of the screen from the game window as well. I picked a button out on the screen that does not appear to have transparency so it would hold the same value pixels. At least that is what I thought. When comparing large to small it is not finding the pixel matches. Upon further inspection of the screen shot through Adobe the pixels are showing a different RGB color(24bit). So pixel 1 (big pic) would be a dark blue and the same pixel on the smaller would be a lighter shade of that blue.
So if the pixels "change" this is going to be more fail that pass I would think. It could be my sample needs to be smaller and I will certainly play with that once I get back home. Just wanted to know if you had to deal with something like pixels being different even though they look solid. Also could it be that my Testing sample is flawed with the method of capture? Should I learn to pull the screen shot off the video stream vs. through a windows screen capture method?
I am trying to get a small SWTOR bot going that is functional now so that I can spend time on learning/building more memory reading or function calling bot. Long way to go on that but gotta start somewhere.
-
Private
can image app have the functio of posititon images in C#. . any help would be appreciated.
-
Member
Bro how can i use that ? İ am new developer. Can you share an example ?
Last edited by Berdar; 01-27-2016 at 07:30 AM.