C# 检查颜色相似性算法太慢
我试图每50毫秒截图一次,删除所有与我一开始决定的颜色不相似的颜色,但检查每个像素颜色的代码部分太慢,所以最后几乎每1.5秒截图一次。。。 代码如下: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
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#编写它,但程序会变得不安全,这通常不是一件好事。当然,这个答案也同样缓慢,因为每次操作都会锁定和解锁