- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我正在尝试使用锁位来增加我的图像检测类,但这会导致代码出现问题,因此它无法运行。我如何才能同时使用 lockbits 和 getpixel 以加快图像检测速度,或者有人可以告诉我一个同样快的替代方案吗?
代码:
static IntPtr Iptr = IntPtr.Zero;
static BitmapData bitmapData = null;
static public byte[] Pixels { get; set; }
static public int Depth { get; private set; }
static public int Width { get; private set; }
static public int Height { get; private set; }
static public void LockBits(Bitmap source)
{
// Get width and height of bitmap
Width = source.Width;
Height = source.Height;
// get total locked pixels count
int PixelCount = Width * Height;
// Create rectangle to lock
Rectangle rect = new Rectangle(0, 0, Width, Height);
// get source bitmap pixel format size
Depth = System.Drawing.Bitmap.GetPixelFormatSize(source.PixelFormat);
// Lock bitmap and return bitmap data
bitmapData = source.LockBits(rect, ImageLockMode.ReadWrite,
source.PixelFormat);
// create byte array to copy pixel values
int step = Depth / 8;
Pixels = new byte[PixelCount * step];
Iptr = bitmapData.Scan0;
// Copy data from pointer to array
Marshal.Copy(Iptr, Pixels, 0, Pixels.Length);
}
static public bool SimilarColors(int R1, int G1, int B1, int R2, int G2, int B2, int Tolerance)
{
bool returnValue = true;
if (Math.Abs(R1 - R2) > Tolerance || Math.Abs(G1 - G2) > Tolerance || Math.Abs(B1 - B2) > Tolerance)
{
returnValue = false;
}
return returnValue;
}
public bool findImage(Bitmap small, Bitmap large, out Point location)
{
unsafe
{
LockBits(small);
LockBits(large);
//Loop through large images width
for (int largeX = 0; largeX < large.Width; largeX++)
{
//And height
for (int largeY = 0; largeY < large.Height; largeY++)
{
//Loop through the small width
for (int smallX = 0; smallX < small.Width; smallX++)
{
//And height
for (int smallY = 0; smallY < small.Height; smallY++)
{
//Get current pixels for both image
Color currentSmall = small.GetPixel(smallX, smallY);
Color currentLarge = large.GetPixel(largeX + smallX, largeY + smallY);
//If they dont match (i.e. the image is not there)
if (!colorsMatch(currentSmall, currentLarge))
//Goto the next pixel in the large image
goto nextLoop;
}
}
//If all the pixels match up, then return true and change Point location to the top left co-ordinates where it was found
location = new Point(largeX, largeY);
return true;
//Go to next pixel on large image
nextLoop:
continue;
}
}
//Return false if image is not found, and set an empty point
location = Point.Empty;
return false;
}
}
最佳答案
您不会希望依赖 getPixel() 进行图像处理;偶尔调用以获取点值(例如在鼠标悬停时)是可以的,但通常最好在图像内存中或在必要时可以转换为位图的某些 2D 数组中进行图像处理。
首先,您可以尝试编写一个方法,使用 LockBits/UnlockBits 提取一个便于操作的数组。完成对数组的操作后,您可以使用不同的 LockBits/UnlockBits 函数将其写回位图。
这是我过去使用过的一些示例代码。第一个函数从位图中返回值的一维数组。由于您知道位图的宽度,因此可以将此一维数组转换为二维数组以进行进一步处理。完成处理后,您可以调用第二个函数将(修改后的)一维数组再次转换为位图。
public static byte[] Array1DFromBitmap(Bitmap bmp){
if (bmp == null) throw new NullReferenceException("Bitmap is null");
Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
BitmapData data = bmp.LockBits(rect, ImageLockMode.ReadWrite, bmp.PixelFormat);
IntPtr ptr = data.Scan0;
//declare an array to hold the bytes of the bitmap
int numBytes = data.Stride * bmp.Height;
byte[] bytes = new byte[numBytes];
//copy the RGB values into the array
System.Runtime.InteropServices.Marshal.Copy(ptr, bytes, 0, numBytes);
bmp.UnlockBits(data);
return bytes;
}
public static Bitmap BitmapFromArray1D(byte[] bytes, int width, int height)
{
Bitmap grayBmp = new Bitmap(width, height, PixelFormat.Format8bppIndexed);
Rectangle grayRect = new Rectangle(0, 0, grayBmp.Width, grayBmp.Height);
BitmapData grayData = grayBmp.LockBits(grayRect, ImageLockMode.ReadWrite, grayBmp.PixelFormat);
IntPtr grayPtr = grayData.Scan0;
int grayBytes = grayData.Stride * grayBmp.Height;
ColorPalette pal = grayBmp.Palette;
for (int g = 0; g < 256; g++){
pal.Entries[g] = Color.FromArgb(g, g, g);
}
grayBmp.Palette = pal;
System.Runtime.InteropServices.Marshal.Copy(bytes, 0, grayPtr, grayBytes);
grayBmp.UnlockBits(grayData);
return grayBmp;
}
这些方法对 Bitmap 像素格式做出的假设可能不适合您,但我希望总体思路是清楚的:使用 LockBits/UnlockBits 从 Bitmap 中提取字节数组,以便您可以编写和调试算法最很容易,然后再次使用 LockBits/UnlockBits 将数组再次写入位图。
为了可移植性,我建议您的方法返回所需的数据类型,而不是在方法本身内操作全局变量。
如果您一直在使用 getPixel(),那么如上所述转换为数组或从数组转换可以显着加快您的代码速度,只需少量的编码工作投入。
关于c# - 使用 lockbits 进行图像处理,替代 getpixel?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12168654/
我正在编写一个 Android 应用程序,它使用 getPixel 读取位图的像素,并且它正在工作,只是它使用了大量的计算能力。因此,我尝试使用 getPixels 代替,并将所有整数保存到整数数组
我正在为我的 Bitmap 使用方法 getPixel 和 setPixel 并且它太慢了(getPixels 也是).我想处理 Bitmap 的每个像素,然后创建另一个 Bitmap。如何通过 Re
无论它变成什么颜色,值检查都保持不变。它应该每秒给我精确像素的 RGB 值 我尝试以递归的方式进行,简化它,在多个对象上进行测试,结果保持不变。 im = pg.screenshot() import
我正在使用一个 ImageView ,我想知道其中的像素颜色,所以我正在使用 getpixel()...方法但它向我展示了一个错误....这就是我使用获取像素方法的方式.. image = Bitm
我在我的 Android 应用程序中使用此代码将位图转换为纯黑白,它可以工作: public Bitmap ConvertToThreshold(Bitmap anythingBmap) {
好吧,这很容易理解,但是由于一些奇怪的原因我无法让它工作。我已经从实际代码中简化了这个例子。 InputStream is = context.getResources().openRawResour
这是我在这个论坛上的第一篇帖子,如果我发错地方或者做错了,请不要责备我,我很少在论坛发帖。所以,我对 GetPixel 函数有这个问题。基本上,它应该返回 x、y 处的颜色小数。我即将发布的代码在 w
直接看代码。鉴于 Bitmap bitmap = BitmapFactory.decodeResource(getResources(), resId); Drawable drawable = ge
正如标题所示,调用 Bitmap.GetPixel 不会产生任何结果。没有为变量赋值,也没有抛出异常。 这是我的测试代码: private void frmStatTracker_Load(objec
在我尝试编写一些代码时,收到此错误: Error 1 'System.Drawing.Image' does not contain a definition for 'GetPixel' and n
我需要组合来自两个 WriteableBitmap 对象的两个颜色值并用它们计算一些东西。因此,我在第一个对象上运行 ForEach 循环,并将其颜色值和第二个对象的颜色值解析为一个方法。 write
现在我有一个完全是空白的黄色窗口。由于某种原因,当我调用 GetPixel() 时,我只得到 0xFFFFFFFF (CLR_INVALID)。这是我的最小化代码: HWND _hwndPP = F
我编写此代码是为了消除视频中因相机故障而导致的恼人模式。问题是要对 2 分钟的视频进行编码,此算法需要超过 2 小时。我想显着减少所需的时间。 该算法遍历每个图像,从那里开始查看每 4 个像素,创建平
我在从生成的位图中读回像素值时遇到了一些问题。我首先使用以下代码在我的类中生成一个名为 maskBitmap 的位图: void generateMaskBitmap() {
我是使用 Android 的新手,现在已经为这个问题努力了四天。我非常感谢有人的帮助。 我在 ImageView 中有一张图片,我想获取用户触摸的图片部分的颜色。为此,我正在使用 Bitmap.get
我创建了一个代表汽车的图像,我用不同的颜色为汽车的每个组件着色,例如引擎盖的 RGB 颜色为 251,252,252。 此图像通过 TileView 显示在屏幕上,我需要实现一个函数来获取我触摸的像素
我正在尝试制作一个非常简单的图 block 引擎。但是,使用 Bitmap.getpixel(x,y)并不总是正确匹配颜色。 0xFFFFFFFF 似乎还不错, 0xFF000000 , 0xFF18
我正在使用 Bitmap.getPixels使用下面的代码在位图图像中间获取一行 1 像素高度: int width = source.getWidth(); int height = source.
我正在创建一个涉及获取部分屏幕颜色的应用程序。为此,我使用 Bitmap.getPixel 方法检索屏幕的指定像素,然后将其转换为 RGB 格式,以便以后更轻松地进行编码。问题是无论我使用 getPi
我如何用更快的东西替换 GetPixel()? 目前我正在使用: temp = GetPixel(hMonitor, 1, 1); if (pixelArray[0] != temp) { p
我是一名优秀的程序员,十分优秀!