Page 1 of 1
[C#] Fast acces to bitmap pixels?
#1
[C#] Fast acces to bitmap pixels?
Posted 19 February 2006 - 05:20 AM
Hi everyone
I've been trying to mess around with image recognition in C# for some time now. But to do that, I need acces to all the pixels in the bitmap individually. At the moment, I'm using getPixel and setPixel. It works, but it's VERY slow. Is there any faster way to acces pixels in a bitmap? Unsafe code maybe?
I've been trying to mess around with image recognition in C# for some time now. But to do that, I need acces to all the pixels in the bitmap individually. At the moment, I'm using getPixel and setPixel. It works, but it's VERY slow. Is there any faster way to acces pixels in a bitmap? Unsafe code maybe?
#2
Re: [C#] Fast acces to bitmap pixels?
Posted 19 February 2006 - 07:43 AM
I'm afriad I don't know very much about working with images programatically...are you just using the Bitmap class? I seem to remember that working in unsafe mode could speed things up, but I've never performed the comparison.
#12
Re: [C#] Fast acces to bitmap pixels?
Posted 08 March 2006 - 09:59 AM
Okay, I'm back with a solution. With some help of a msdn article, I made this class
:
Use it, if you find it useful
You can use it like this:
UnsafeBitmap your_fast_bitmap = new UnsafeBitmap(old_safe_bitmap);
your_fast_bitmap.LockBitmap();
PixelData pixel = your_fast_bitmap.getPixel(3, 4);
//more setpixel/getpixel calls here!
your_fast_bitmap.UnlockBitmap();
Here's the article on msdn that deals with unsafe bitmap access: http://msdn.microsof...arp11152001.asp
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;
namespace SampleGrabberNET
{
public unsafe class UnsafeBitmap
{
Bitmap bitmap;
// three elements used for MakeGreyUnsafe
int width;
BitmapData bitmapData = null;
Byte* pBase = null;
public UnsafeBitmap(Bitmap bitmap)
{
this.bitmap = new Bitmap(bitmap);
}
public UnsafeBitmap(int width, int height)
{
this.bitmap = new Bitmap(width, height, PixelFormat.Format24bppRgb);
}
public void Dispose()
{
bitmap.Dispose();
}
public Bitmap Bitmap
{
get
{
return(bitmap);
}
}
private Point PixelSize
{
get
{
GraphicsUnit unit = GraphicsUnit.Pixel;
RectangleF bounds = bitmap.GetBounds(ref unit);
return new Point((int) bounds.Width, (int) bounds.Height);
}
}
public void LockBitmap()
{
GraphicsUnit unit = GraphicsUnit.Pixel;
RectangleF boundsF = bitmap.GetBounds(ref unit);
Rectangle bounds = new Rectangle((int) boundsF.X,
(int) boundsF.Y,
(int) boundsF.Width,
(int) boundsF.Height);
// Figure out the number of bytes in a row
// This is rounded up to be a multiple of 4
// bytes, since a scan line in an image must always be a multiple of 4 bytes
// in length.
width = (int) boundsF.Width * sizeof(PixelData);
if (width % 4 != 0)
{
width = 4 * (width / 4 + 1);
}
bitmapData =
bitmap.LockBits(bounds, ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
pBase = (Byte*) bitmapData.Scan0.ToPointer();
}
public PixelData GetPixel(int x, int y)
{
PixelData returnValue = *PixelAt(x, y);
return returnValue;
}
public void SetPixel(int x, int y, PixelData colour)
{
PixelData* pixel = PixelAt(x, y);
*pixel = colour;
}
public void UnlockBitmap()
{
bitmap.UnlockBits(bitmapData);
bitmapData = null;
pBase = null;
}
public PixelData* PixelAt(int x, int y)
{
return (PixelData*)(pBase + y * width + x * sizeof(PixelData));
}
}
public struct PixelData
{
public byte blue;
public byte green;
public byte red;
}
}
Use it, if you find it useful
You can use it like this:
UnsafeBitmap your_fast_bitmap = new UnsafeBitmap(old_safe_bitmap);
your_fast_bitmap.LockBitmap();
PixelData pixel = your_fast_bitmap.getPixel(3, 4);
//more setpixel/getpixel calls here!
your_fast_bitmap.UnlockBitmap();
Here's the article on msdn that deals with unsafe bitmap access: http://msdn.microsof...arp11152001.asp
This post has been edited by microchip: 08 March 2006 - 10:04 AM
#13
Re: [C#] Fast acces to bitmap pixels?
Posted 08 May 2008 - 07:04 AM
I have a question....what if i am wanting to look for a pattern within a screen shot. Specifically for mapping of game areas? I have a VB.net form that will automate screenshots ever few seconds but currently am unable to find a way to do a matching algorithm based on a predefined pattern. Reason for the pattern is cause different users may have this pattern located in different areas of the screen during play.
this would be the pattern area:

The gold area ring for the most part....not too worried about the compass points. If i could streamline this before the screenshot that would be great but at minimal....taking the screenshot and then searching the bitmap created for this pattern is the least i want to be able to do.
I realize this is the C# board but i can easily transverse from c# to vb.net with little to no problem. This thread just seems to be the more in line with what i am trying to do but is not the exact solution i am looking for. At least point me in the correct direction
this would be the pattern area:

The gold area ring for the most part....not too worried about the compass points. If i could streamline this before the screenshot that would be great but at minimal....taking the screenshot and then searching the bitmap created for this pattern is the least i want to be able to do.
I realize this is the C# board but i can easily transverse from c# to vb.net with little to no problem. This thread just seems to be the more in line with what i am trying to do but is not the exact solution i am looking for. At least point me in the correct direction
This post has been edited by woodjom: 08 May 2008 - 07:12 AM
#14
Re: [C#] Fast acces to bitmap pixels?
Posted 18 May 2008 - 04:19 PM
hey. Thanks for the unsafe bitmap code microchip, saved me a lot of effort trying to churn out some code in a hurry.
To WOW guy (it is wow right?)
If you are trying to do that match, the first thing I would do would be to exlude all the pixels that are the wrong colour. The map thing isnt semitransparent or affected by light in the game, so remove everything but the ring using RGB matching. Remove the rest just by setting it to black, and make a note to just not evaluate anything black later.
You may find that some of the screen is just the right colour later on. This would be quite inconvenient. You can remove this by 2 methods:
SIMPLE METHOD:
if, after some experimenting, you find that only a small bit of the screen is the same clour as the map surround, you can just find the biggest lump of "right colour", by like taking a sum of the number of pixels in each quater of the screen that are the right colour, then subdividing or something. Dead easy to code, maybe no the most efficient though... and only works if map is biggest.
MIDDLE METHOD:
or you can take into account that the map surround is the only bit never moving by keeping a buffer of a few maps, and comparing say current clip to a clip 6 frames ago. not moved? probably the map. Then do the simple method. again easy to code up, but a bit more computationaly expensive.
THE HARD WAY:
http://ieeexplore.ie...rnumber=4118765
if you can get hold of this paper, its a really cool fast way of shape matching, and can be configured to be learning :-). Do 1, and maybe 2, then run that, and your map thing will almost always be found regardless of what colour the background is.
To WOW guy (it is wow right?)
If you are trying to do that match, the first thing I would do would be to exlude all the pixels that are the wrong colour. The map thing isnt semitransparent or affected by light in the game, so remove everything but the ring using RGB matching. Remove the rest just by setting it to black, and make a note to just not evaluate anything black later.
You may find that some of the screen is just the right colour later on. This would be quite inconvenient. You can remove this by 2 methods:
SIMPLE METHOD:
if, after some experimenting, you find that only a small bit of the screen is the same clour as the map surround, you can just find the biggest lump of "right colour", by like taking a sum of the number of pixels in each quater of the screen that are the right colour, then subdividing or something. Dead easy to code, maybe no the most efficient though... and only works if map is biggest.
MIDDLE METHOD:
or you can take into account that the map surround is the only bit never moving by keeping a buffer of a few maps, and comparing say current clip to a clip 6 frames ago. not moved? probably the map. Then do the simple method. again easy to code up, but a bit more computationaly expensive.
THE HARD WAY:
http://ieeexplore.ie...rnumber=4118765
if you can get hold of this paper, its a really cool fast way of shape matching, and can be configured to be learning :-). Do 1, and maybe 2, then run that, and your map thing will almost always be found regardless of what colour the background is.
Page 1 of 1

Reply




MultiQuote





|