ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

c#-对于循环,应用程序挂起

2019-11-05 14:09:30  阅读:197  来源: 互联网

标签:loops for-loop c nested-loops


好吧,我正在创建一个应用程序,我在使用for循环来基本上读取图像的每个像素,寻找像素颜色(简单的东西)中的图案.无论如何,由于某种原因,我的应用程序只是锁定而从未恢复到正常状态.我一次又一次地遍历代码,而没有看到任何实际的问题.

我唯一注意到的是ScanPixelsLater中的for循环可能提前退出.我已经尽可能地注释了代码,

private Point topLeftc, bottomLeftc, topRightc, bottomRightc;

/// <summary>
/// Starts the initial looping process, designed only to loop through ONCE, ScanPixelsLater takes over
/// </summary>
/// <param name="img">Image to scan</param>
public void ScanPixels(Bitmap img)
{
    int whitePixel = 0;

    for (int y = 100; y < img.Height; y++)
    {

        for (int x = 100; x < img.Width; x++)
        {

            if (img.GetPixel(x, y) == Color.FromArgb(255, 255, 255, 255))
            {
                // img.SetPixel(x, y, Color.Green);
                whitePixel++;

            }
            else { whitePixel = 0; }


            if (whitePixel == 18)
            {
                whitePixel = 0;
                topLeftc = new Point(x - 18, y);
                DetectNextWhiteLine(topLeftc, img);

            }
        }
    }


}


/// <summary>
/// First creates the TopRight value via using the last pixel in x range, and using the current Y value
/// Then a Y loop is started 10 pixels down, within this loop is another X loop which scans the X range
/// If 10 consecutive white pixels are found, the TopLeft X value and the current Y value are used to map the 
/// BottomLeft and BottomRight coordinates. Finally a new Point is created which starts (x = 1) and (y = currentYValue + 2)
/// The ScanPixelsLater method is then called, passing the new Point (newLocation).
/// 
/// </summary>
/// <param name="p">The x and y value of where the pixels were found</param>
/// <param name="img">Image being used</param>
private void DetectNextWhiteLine(Point p, Bitmap img)
{

    int whitePixel = 0;
    topRightc = new Point(img.Width, topLeftc.Y);

    for (int y = p.Y + 10; y < img.Height; y++)
    {

        for (int x = p.X - 5; x < img.Width; x++)
        {
            if (img.GetPixel(x, y) == Color.FromArgb(255, 255, 255, 255))
            {
                whitePixel++;
            }
            else
            {
                whitePixel = 0;
            }

            if (whitePixel == 10)
            {
                bottomLeftc = new Point(topLeftc.X, y);
                bottomRightc = new Point(img.Width, y);
                Cords.Add(new Coordinates(topLeftc, topRightc, bottomLeftc, bottomRightc));

                Point newLocation = new Point(1, y + 2);
                calls++;
                ScanPixelsLater(newLocation, img); //rescan the image from new y axis 
            }
        }
    }

}



/// <summary>
/// Loops through the pixels based on the p parameter, if 15 white pixels are found, the location (x & y) is
/// passed to the DetectNextWhiteLine method which fixes the next line with a similar number of white pixels.
/// </summary>
/// <param name="p">The Point(x,y) at which to start scanning</param>
/// <param name="img"></param>
private void ScanPixelsLater(Point p, Bitmap img)
{

    int whitePixel = 0;

    for (int y = p.Y; y < img.Height; y++)
    {

        for (int x = p.X; x < img.Width; x++)
        {
            if (img.GetPixel(x, y) == Color.FromArgb(255, 255, 255, 255))
            {
                whitePixel++;
            }
            else
            {
                whitePixel = 0;
            }

            if (whitePixel == 15)
            {
                bottomLeftc = new Point(topLeftc.X, y);
                topLeftc = new Point(x - 15, y);
                calls++;
                DetectNextWhiteLine(topLeftc, img);
            }

        }
    }

    // only want this to execute after all the pixels within the entire img have been read
    // possibly executing early.

    DrawWhiteLines(img);
    AppArgs aa = new AppArgs(true);
    Change(this, aa); // custom event handler, fired behind form to update GUI

}

解决方法:

因此,要了解您的应用程序为何挂起,您需要了解WinForm应用程序的工作原理.

您的UI所运行的线程也具有所谓的消息泵.此消息泵包含从操作系统(和其他来源)传递到所有UI元素的消息.他们告诉他们何时更改状态,何时重绘自身等.当您的循环很长时,消息泵将无法处理消息.获取排队,但从未处理,这就是应用程序“挂起”的含义.

您的应用程序永远都不可能恢复.您的循环最终将结束,您的UI将再次变得响应(假设我没有在某个地方错过无限循环,但我不认为我做到了).但是,GDI GetPixel方法确实非常慢,并且如果您的图像很大,那么这组循环将需要很长时间才能完成.您可能必须深入研究不安全的上下文,并使用LockBits获取指向图像内存的指针.这里有很多如何做到这一点的例子.

编辑:在更仔细地查看您的代码后,也很明显它效率相对较低.那里至少有6个嵌套的for循环嵌套层,因此当您只需要单次扫描时,实际上就需要多次扫描图像.

图像处理是一个资源密集的过程.您需要小心,以尽可能高效地完成所有性能密集型工作.

标签:loops,for-loop,c,nested-loops
来源: https://codeday.me/bug/20191105/1995526.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有