在我的代码中,输出是一个图像,其每个像素都是使用嵌套循环确定的。
1)如何在循环中构建输出图像时强制窗口打开并显示输出图像? (当一切都完成时,窗口会出现。我不想要这个。)
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
}
}
答案 0 :(得分:1)
您可以通过将图像放在单独的线程上并使用GetPixel和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);
}
}
}
如果你想加快这一点,你可以启动两个或更多任务,每个任务并行工作(例如,一个线程从头开始,另一个在末尾,另一个在中间可能,等等)。只要确保你的线程没有“重叠”。
另一种加快速度的方法是使用指针代替GetPixel()
和SetPixel()
。您必须将代码标记为unsafe
。
答案 1 :(得分:0)
将您的代码放在后台Worker =&gt;做工作 将启动一个单独的线程
答案 2 :(得分:-1)
我不是WinForms专家我更像是WPF类型。但我有一个运行稳定的30fps的应用程序,这比人类可以检测到的更快。我真的不太明白你想做什么。你必须单独blit每个像素,但实时显示? ImageBox派生自Windows Forms PictureBox,这是我不认为的工作。
您可以尝试移动到WPF,并使用WriteableBitmap作为ImageSource的ImageSource或Canvas对象的背景。 WriteableBitmap允许您访问每个像素,但刷新率由WPF控制,显示器刷新率由AC当前频率控制。
道格