I need to compare two images and see if they are the same.
The images only contain text.
I have an image on the hard drive saved and I need to see if it is the same as the one I am downloading.
I tried with this code to establish a margin of error of 5%, but the main problem I have is that the text of image can be rotated between 0 and 30 degrees or 0 and -30
int width;
int height;
if (bmp1.width < bmp2.width)
{
width = bmp1.width;
}
else
{
width = bmp2.width;
}
if (bmp1.heigth < bmp2.width)
{
heigth = bmp1.heigth;
}
else
{
heigth = bmp2.heigth;
}
int contador = 0;
for (int x = 0; x < width; x++)
{
for (int y = 0; y < height; y++)
{
if (bmp1.GetPixel(x, y) == bmp2.GetPixel(x, y))
{
contador++
}
}
}
int similar_percent = (contador / (height * width) * 100);
I leave two small examples of the images
Related
I'd like to figure out how I can add a 1 pixel border in between each frame that my spritesheet creator generates, can anyone help?
The function below takes an array of images and turns them into a table filled with bitmaps.
The program is supposed to take a gif and turn it into multiple spritesheets, so that it can be displayed in a game engine. That part is working fine, but I'd like to add a 1 pixel border in between each frame.
public Bitmap[] combineFrames(Image[] images, int columns)
{
int rows = columns;
int imagesPerSheet = rows * columns;
int sheets = (int)Math.Ceiling((double)images.Length / imagesPerSheet);
Bitmap[] mapTable = new Bitmap[55]; //55 being the max #sheets
for (int x = 0; x < sheets; x++)
{
Bitmap bitmap = new Bitmap(images[0].Width * columns, images[0].Height * rows);
Graphics graphics = Graphics.FromImage(bitmap);
int L = 0;
int remainingNFrames = (images.Length - (imagesPerSheet * x));
if (remainingNFrames < imagesPerSheet)
{
L = remainingNFrames;
}
else
{
L = imagesPerSheet;
}
for (int i = 0; i <= L; i++)
{
int formulizedProduct = imagesPerSheet * (x) + (i);
if (formulizedProduct == images.Length) { break; } //should always be length - 1
Image image = images[formulizedProduct]; //16*x+i
int X = (image.Width * ((i - 1) % columns));
int Y = (image.Height * (int)((double)(i - 1) / columns));
graphics.DrawImage(
image,
X, //I feel like I'd have to adjust this part and the part below, but I'm not really sure.
Y
);
}
mapTable[x] = bitmap;
}
return mapTable;
}
Thanks.
I need to check how similar two images are. I need to have this in a number; a percentage.
public static void Compare(Bitmap bmp1, Bitmap bmp2)
{
int width;
int height;
if (bmp1.width < bmp2.width)
{
width = bmp1.width;
}
else
{
width = bmp2.width;
}
if (bmp1.heigth < bmp2.width)
{
heigth = bmp1.heigth;
}
else
{
heigth = bmp2.heigth;
}
int contador = 0;
for (int x = 0; x < width; x++)
{
for (int y = 0; y < height; y++)
{
if (bmp1.GetPixel(x, y) == bmp2.GetPixel(x, y))
{
contador++
}
}
}
Messagebox.Show("The percent of similar is:" + (contador / (height * width) * 100).ToString());
}
This works perfectly while the images are not of different size, because for example when putting a white line to one of the 2 images the percentage of comparison is 0% that if I put it at the beginning and if I put it at the end then it does not take it into consideration.
I surfed quite looking but I always find examples of images that have the same height and length.
Is there any way to see how much similarity has one image of the other? The resources are not problems since usually the images are quite small.
I would like to find an object on a bitmap using its HSV color. I know there already are some topics created about this issue, but they seem not to work on Android (I didn't find System.Drawing.Imaging on Android) or to be less efficient than the algorithm I already created:
public Rect FindObjectOnBitmap(Bitmap bm)
{
bm.GetPixels(pixels, 0, bm.Width, 0, 0, bm.Width, bm.Height);
// Get the matching pixels.
for(int x = 0; x<bm.Width; x++)
for (int y = 0; y < bm.Height; y++)
{
Color color = new Color(pixels[x + bm.Width * y]);
pixelsMatch[x,y] = (color.GetBrightness() > Settings.Tracker.blackFilter && color.GetSaturation() > Settings.Tracker.whiteFilter) && (Angle(Settings.Tracker.hue, color.GetHue()) < Settings.Tracker.sensitivity);
}
Rect objectRect = null;
int maxNbPixel = 0;
// for each matching pixel
for (int x = 0; x < bm.Width; x ++)
for (int y = 0; y < bm.Height; y ++)
if(pixelsMatch[x, y])
{
int nbPixel = 0;
Rect objectRectTemp = new Rect(x, y, x, y);
Queue<Pixel> zone = new Queue<Pixel>();
zone.Enqueue(new Pixel(x, y));
while(zone.Count != 0)
{
Pixel px = zone.Dequeue();
nbPixel++;
// Updates object position
if (px.x < objectRectTemp.Left)
objectRectTemp.Left = px.x;
if (px.x > objectRectTemp.Right)
objectRectTemp.Right = px.x;
if (px.y < objectRectTemp.Bottom)
objectRectTemp.Bottom = px.y;
if (px.y > objectRectTemp.Top)
objectRectTemp.Top = px.y;
// for each nearby pixel
for (int side = 0; side < 4; side++)
{
Pixel sidePx = px.Side(side);
if (sidePx.x >= 0 && sidePx.x < bm.Width && sidePx.y >= 0 && sidePx.y < bm.Height)
{
if (pixelsMatch[sidePx.x, sidePx.y])
{
zone.Enqueue(sidePx);
pixelsMatch[sidePx.x, sidePx.y] = false;
}
}
}
}
// Save the object if it is big enough.
if(nbPixel > maxNbPixel && nbPixel >= 4)
{
maxNbPixel = nbPixel;
objectRect = objectRectTemp;
}
}
return objectRect;
}
// Function comparing hues.
static float Angle(float deg1, float deg2)
{
if (Math.Abs(deg1 - deg2) > 180f)
return (360f - Math.Abs(deg1 - deg2));
else
return Math.Abs(deg1 - deg2);
}
However, I am reading a stream, and this algorithm is also not efficient enough since I get 0.1 fps on a 640x480 image... I get a good fps only if I create the bitmap with a smaller resolution than the real image (for example 40x30). That enables me to detect big or close objects with a bad precision (position and size).
How can I increase the efficiency enough, knowing I am on an ANDROID device...
Thanks in advance.
PS: Sorry for my poor English ^^
I'm attempting to get the bounds of the edges of interest in a binary image using the following method. Sadly my maths seems to be letting me down and I'm only getting a rectangle 2px smaller in each dimension than the original image.
Can someone show me where I have gone wrong?
Note. FastBitmap is a class that allows fast access to pixel data.
private Rectangle FindBox(Bitmap bitmap, byte indexToRemove)
{
int width = bitmap.Width;
int height = bitmap.Height;
int minX = width;
int minY = height;
int maxX = 0;
int maxY = 0;
using (FastBitmap fastBitmap = new FastBitmap(bitmap))
{
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
if (fastBitmap.GetPixel(x, y).B == indexToRemove)
{
if (x < minX)
{
minX = x;
}
if (x > maxX)
{
maxX = x;
}
if (y < minY)
{
minY = y;
}
if (y > maxY)
{
maxY = y;
}
}
}
}
}
// check
if ((minX == width) && (minY == height) && (maxX == 0) && (maxY == 0))
{
minX = minY = 0;
}
return new Rectangle(minX, minY, maxX - minX + 1, maxY - minY + 1);
}
The image I'm testing.
You appear to be checking EVERY pixel to see if a match exists in any x and y. Instead, what you want to do is check the minx, maxx, miny, and maxy separately.
For the minY, you want start at the top and check each row down until you hit a y row that has a matching pixel.
For the maxY, you want start at the bottom and check each row up until you hit a y row that has a matching pixel.
For the minX, you want start at the left and check each column until you hit a x column that has a matching pixel.
For the maxX, you want start at the right and check each column until you hit a x column that has a matching pixel.
Something like this:
minY = getMinY(fastBitmap, indexToRemove);
maxY = getMinY(fastBitmap, indexToRemove);
minX = getMinY(fastBitmap, indexToRemove);
maxX = getMinY(fastBitmap, indexToRemove);
int getMinY(Bitmap bitmap, byte indexToRemove)
{
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
if (fastBitmap.GetPixel(x, y).B == indexToRemove)
{
return y;
}
}
}
return 0;
}
int getMaxY(Bitmap bitmap, byte indexToRemove)
{
for (int y = height; y > 0; y--)
{
for (int x = 0; x < width; x++)
{
if (fastBitmap.GetPixel(x, y).B == indexToRemove)
{
return y;
}
}
}
return height;
}
etc...
You should be able to write the getMinX and getMaxY yourself.
I have tried this code for converting a bitmap to pure black and white - not greyScale, but this gives me a pure black image.
public Bitmap blackwhite(Bitmap source)
{
Bitmap bm = new Bitmap(source.Width,source.Height);
for(int y=0;y<bm.Height;y++)
{
for(int x=0;x<bm.Width;x++)
{
if (source.GetPixel(x, y).GetBrightness() > 0.5f)
{
source.SetPixel(x,y,Color.White);
}
else
{
source.SetPixel(x,y,Color.Black);
}
}
}
return bm;
}
What can cause such a problem? Is there any alternate method to this?
I know this answer is way too late but I just figured it out and hope it helps other people having this problem.
I get the average brightness of the picture and use that as the threshold for setting pixels to black or white. It isn't 100% accurate and definitely isn't optimized for time complexity but it gets the job done.
public static void GetBitmap(string file)
{
using (Bitmap img = new Bitmap(file, true))
{
// Variable for image brightness
double avgBright = 0;
for (int y = 0; y < img.Height; y++)
{
for (int x = 0; x < img.Width; x++)
{
// Get the brightness of this pixel
avgBright += img.GetPixel(x, y).GetBrightness();
}
}
// Get the average brightness and limit it's min / max
avgBright = avgBright / (img.Width * img.Height);
avgBright = avgBright < .3 ? .3 : avgBright;
avgBright = avgBright > .7 ? .7 : avgBright;
// Convert image to black and white based on average brightness
for (int y = 0; y < img.Height; y++)
{
for (int x = 0; x < img.Width; x++)
{
// Set this pixel to black or white based on threshold
if (img.GetPixel(x, y).GetBrightness() > avgBright) img.SetPixel(x, y, Color.White);
else img.SetPixel(x, y, Color.Black);
}
}
// Image is now in black and white
}