Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/327.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 检查颜色相似性算法太慢_C#_.net_Image Processing - Fatal编程技术网

C# 检查颜色相似性算法太慢

C# 检查颜色相似性算法太慢,c#,.net,image-processing,C#,.net,Image Processing,我试图每50毫秒截图一次,删除所有与我一开始决定的颜色不相似的颜色,但检查每个像素颜色的代码部分太慢,所以最后几乎每1.5秒截图一次。。。 代码如下: public int upX = 114; public int upY = 28; public Size size = new Size(1137,640); public Color rosa = Color.FromArgb(255, 102, 153); public int tollerance = 20; private void

我试图每50毫秒截图一次,删除所有与我一开始决定的颜色不相似的颜色,但检查每个像素颜色的代码部分太慢,所以最后几乎每1.5秒截图一次。。。 代码如下:

public int upX = 114;
public int upY = 28;
public Size size = new Size(1137,640);
public Color rosa = Color.FromArgb(255, 102, 153);
public int tollerance = 20;

private void button1_Click(object sender, EventArgs e){
  button1.Enabled = false;
  do{
    Bitmap bmpScreenshot = screenshot();
    deleteColors(bmpScreenshot, rosa);
    picturebox1.image = bmpScreenshot;
    Application.DoEvents();
  } while (true);
}

public Bitmap screenshot() {
  Bitmap bmpScreenshot = new Bitmap(size.Width, size.Height, PixelFormat.Format16bppRgb555);
  Graphics gfxScreenshot = Graphics.FromImage(bmpScreenshot);
  gfxScreenshot.CopyFromScreen(upX, upY, 0, 0, size);
  return bmpScreenshot;
}

public void deleteColors(Bitmap bitmap, Color colorToSave) {
  for (int i = 0; i < bitmap.Width; i++){
    for (int j = 0; j < bitmap.Height; j++){
      Color c = bitmap.GetPixel(i, j);
      if (!colorsAreSimilar(c, colorToSave, tollerance)){
        bitmap.SetPixel(i, j, Color.White);
      }
     }
   }
 }

public bool colorsAreSimilar(Color a, Color b, int tollerance) {
  if (Math.Abs(a.R - b.R) < tollerance && Math.Abs(a.G - b.G) < tollerance && Math.Abs(a.B - b.B) < tollerance) {
    return true;
  }
  return false;
}
public int upX=114;
公共整数upY=28;
公共尺寸=新尺寸(1137640);
公共颜色rosa=Color.FromArgb(255、102、153);
公共容忍度=20;
私有无效按钮1\u单击(对象发送者,事件参数e){
按钮1.启用=错误;
做{
位图bmpScreenshot=屏幕截图();
删除颜色(bmpScreenshot、rosa);
picturebox1.image=bmpScreenshot;
Application.DoEvents();
}虽然(正确);
}
公共位图截图(){
位图bmpScreenshot=新位图(size.Width、size.Height、PixelFormat.Format16bppRgb555);
Graphics gfxScreenshot=Graphics.FromImage(bmpScreenshot);
gfxScreenshot.CopyFromScreen(upX,upY,0,0,大小);
返回bmpScreenshot;
}
公共void deleteColors(位图、颜色colorToSave){
对于(int i=0;i
截图部分需要17到21毫秒,所以它已经太高了,但是删除部分需要1300毫秒,所以我想在之前解决这个问题,但是。。。我不知道我能做些什么使代码更轻。

你试过使用吗?它将位图锁定在系统内存中,因此您可以对其进行原始访问,这比使用
GetPixel
SetPixel
方法快得多

var bmp = /* open your bitmap */
// The area you want to work on. In this case the full bitmap
Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
System.Drawing.Imaging.BitmapData bmpData = bmp.LockBits(rect,
                    System.Drawing.Imaging.ImageLockMode.ReadWrite,
                    bmp.PixelFormat);
// Obtain a pointer to the data and copy it to a buffer
IntPtr ptr = bmpData.Scan0;
var buffer = new byte[Math.Abs(bmpData.Stride) * bmp.Height];
System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, bytes);

for (int counter = 0; counter < rgbValues.Length; counter += 3)
{
    // Here you can edit the buffer
}

// Copy the data back to the bitmap and unlock it
System.Runtime.InteropServices.Marshal.Copy(rgbValues, 0, ptr, bytes);
bmp.UnlockBits(bmpData);
var bmp=/*打开位图*/
//您要处理的区域。在本例中,将显示完整位图
矩形rect=新矩形(0,0,bmp.Width,bmp.Height);
System.Drawing.Imaging.BitmapData bmpData=bmp.LockBits(rect,
System.Drawing.Imaging.ImageLockMode.ReadWrite,
像素格式);
//获取指向数据的指针并将其复制到缓冲区
IntPtr ptr=bmpData.Scan0;
var buffer=新字节[Math.Abs(bmpData.Stride)*bmp.Height];
System.Runtime.InteropServices.Marshal.Copy(ptr,rgbvalue,0,字节);
对于(int counter=0;counter

您可以找到如何使用它的另一个示例。

如果您担心性能,我强烈建议不要使用
GetPixel()
SetPixel()
方法

尝试编写自己的
GetPixel()
SetPixel()
,例如使用
BitmapData

        public static Color GetPixel(Bitmap bmp, int x, int y)
        {
            BitmapData bitmapData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
            int stride = bitmapData.Stride;
            Color c;
            unsafe
            {
                Byte* ptr = (byte*)bitmapData.Scan0;
                int red = ptr[(x * 3) + y * stride];
                int green = ptr[(x * 3) + y * stride + 1];
                int blue = ptr[(x * 3) + y * stride + 2];
                c = Color.FromArgb(red, green, blue);
            }
            bmp.UnlockBits(bitmapData);
            return c;
        }

        public static void SetPixel(Bitmap bmp, int x, int y, Color c)
        {
            BitmapData bitmapData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
            int stride = bitmapData.Stride;
            unsafe
            {
                Byte* ptr = (byte*)bitmapData.Scan0;
                ptr[(x * 3) + y * stride] = c.R;
                ptr[(x * 3) + y * stride + 1] = c.G;
                ptr[(x * 3) + y * stride + 2] = c.B;
            }
            bmp.UnlockBits(bitmapData);
        }

在我身上跳出来的一件事是,我会用C++编写,截图,所有的都会更快。然后将其设置为dll,并从C#调用它。您可以使用锁位并用C#编写它,但程序会变得不安全,这通常不是一件好事。当然,这个答案也同样缓慢,因为每次操作都会锁定和解锁