在循环中创建图像时实时显示图像

Display an image in real time as it is being created in a loop

在我的代码中,输出是一个图像,每个像素都是使用嵌套循环确定的。

1) 如何强制 window 打开并显示在循环中构建的输出图像? (window 当一切都完成时出现。我不想要这个。)

2) 如何在循环进行时逐行(甚至逐像素)显示输出。用户必须具有实时获取输出的意识。

    outImage = new Image<Hsv, Byte>(numberOfColumns, numberOfRows);
    byte[,,] pixelValue = outImage.Data;
        for (int i = 0; i < numberOfRows - 1; i++)
        {
            for (int j = 0; j < numberOfColumns - 1; j++)
            {
                //pixelValue[i, j, k] is determined here using some other functions
                imageBox1.Image = outImage; //too slow and impossible                 
            }
        }

我不是 WinForms 专家,我更喜欢 WPF 类型。但我有一个应用程序 运行 稳定的 30fps,这比人类检测速度更快。我真的不太明白你想在这里做什么。你必须单独 blit 每个像素,但要实时显示? ImageBox 派生自 Windows Forms PictureBox,我认为这行不通。

您可以尝试移动到 WPF,并为 Image 对象的 ImageSource 或 Canvas 对象的背景使用 WriteableBitmap。 WriteableBitmap 将允许您访问每个像素,但刷新率由 WPF 控制,显示器刷新率由交流电流频率控制。

道格

通过将图像放在单独的线程上并使用 GetPixel and SetPixel,您可以实时逐个像素地显示图像。请记住,尽管这些方法很慢,如果您要显示高分辨率图片,则需要一段时间。

您要做的是创建一个带有图片框控件的窗体。接下来,创建一个包含您要显示的图像的 Bitmap 对象。您可以使用这样的行来执行此操作:

Bitmap _bmp = new Bitmap(Image.FromFile(@"C:\MyImage.jpg"));

接下来,在您表单的 shown 事件中,分拆一个新任务来完成这项工作,这样 GUI 就不会锁定:

private void Form1_Shown(object sender, EventArgs e)
{
    Task.Factory.StartNew(ShowImage);
}

每次显示表单时,该行都会分出一个新线程。该线程将分叉并调用 ShowImage(),它应该如下所示:

private void ShowImage()
{
    Graphics g = pbImage.CreateGraphics();

    for (int x = 0; x < _bmp.Width; x++)
    {
        for (int y = 0; y < _bmp.Height; y++)
        {
            Color c = _bmp.GetPixel(x, y);
            if (pbImage.InvokeRequired)
            {
                var x1 = x;
                var y1 = y;
                pbImage.BeginInvoke((Action) (() =>
                {
                    g.FillRectangle(new SolidBrush(c), x1, y1, 1, 1);
                }));
            }
            else
            {
                g.FillRectangle(new SolidBrush(c), x, y, 1, 1);
            }
            System.Threading.Thread.Sleep(1);
        }
    }
}

如果你想加快一点速度,你可以启动两个或更多任务,每个任务并行工作(例如,一个线程在开头开始,另一个在结尾,另一个可能在中间,等等) ).只要确保您的话题没有 "overlap".

另一种加快速度的方法是使用指针代替 GetPixel()SetPixel()。不过,您必须将代码标记为 unsafe

将你的代码放在后台 Worker => 做工作 将启动一个单独的线程