如下图所示,我有一个简单的WinForms应用程序,它的右侧有一个主组合框,根据我选择的屏幕数量,我可以获得相同数量的动态创建的组合框和图片框。在这个例子中,我选择了4。
如下面的代码所示,我试图创建一个多线程进程,其中根据我在动态创建的组合框中选择的选项(可用相机),然后我想在同一个索引图片框中显示图像流。例如,如果我在组合框1中选择一个相机,那么我想在图片框1中显示它。
private void comboBoxCameraSelection_SelectedIndexChanged(object sender, EventArgs e)
{
panelComboboxes.Controls.Clear();
tableLayoutPanel1.Controls.Clear();
string selectedValue = comboBoxCameraSelection.SelectedIndex.ToString();
int numNewPictureBoxes = Int32.Parse(selectedValue) + 1;
// Set cell border style with a margin of 1 pixel
tableLayoutPanel1.CellBorderStyle = TableLayoutPanelCellBorderStyle.Inset;
for (int i = 0; i < numNewPictureBoxes; i++)
{
numComboBoxes++;
ComboBox newComboBox = new ComboBox();
newComboBox.Name = "comboBox" + numComboBoxes.ToString();
newComboBox.Size = new System.Drawing.Size(100, 21);
newComboBox.Location = new System.Drawing.Point(10, 50 + numComboBoxes * 25);
newComboBox.DropDownStyle = ComboBoxStyle.DropDownList;
newComboBox.Dock = DockStyle.Top;
LoadCameraList(newComboBox);
newComboBox.SelectedIndexChanged += new EventHandler(comboBox_SelectedIndexChanged);
panelComboboxes.Controls.Add(newComboBox);
PictureBox pb = new PictureBox();
pb.SizeMode = PictureBoxSizeMode.StretchImage;
pb.Dock = DockStyle.Fill;
pb.Anchor = AnchorStyles.None;
pb.Margin = new Padding(1); // Add a margin of 1 to the picture box
tableLayoutPanel1.Controls.Add(pb);
}
numComboBoxes = 0;
}
private void comboBox_SelectedIndexChanged(object sender, EventArgs e)
{
ComboBox? comboBox = sender as ComboBox;
if (comboBox != null)
{
int cameraIndex = int.Parse(comboBox.Name.Replace("comboBox", ""));
int selectedItemIndex = comboBox.SelectedIndex;
Debug.WriteLine("Selected camera index: " + cameraIndex + ", Selected item index: " + selectedItemIndex);
PictureBox pb = (PictureBox)tableLayoutPanel1.Controls[cameraIndex-1];
camera = new Thread(() => CaptureCameraCallback(selectedItemIndex-1, pb));
camera.Start();
}
}
private void CaptureCameraCallback(int camInd,PictureBox pictureBox)
{
frame = new Mat();
capture = new VideoCapture(camInd);
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("image/jpeg"));
var apiUrl = "http://192.168.0.136:5000/object_detection";
//capture.Open(2);
while (isCameraRunning == 1)
{
capture.Read(frame);
// Convert the frame to a JPEG image
var buffer = new byte[frame.Width * frame.Height * frame.ElemSize()];
Cv2.ImEncode(".jpg", frame, out buffer);
// Send the JPEG image to the Flask API
var content = new ByteArrayContent(buffer);
content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("image/jpeg");
var response = client.PostAsync(apiUrl, content).Result;
var imageData = response.Content.ReadAsByteArrayAsync().Result;
Image img;
using (var stream = new MemoryStream(imageData))
{
img = Image.FromStream(stream);
}
pictureBox.Image = img;
}
}
在运行我的脚本后,我没有得到任何错误或任何类型的异常。但没有任何东西显示到图片框。
我相信我在comboBox_SelectedIndexChanged
方法中传递图片框时犯了一个错误。也许我引用错了?
我希望我采取的一般方法是正确的,希望有人能帮我解决...
谢谢!
1条答案
按热度按时间xsuvu9jc1#
我假设
CaptureCameraCallback
在后台线程上运行。您只能从UI线程更新UI:在某些情况下,你可能需要调用
Control.Invalidate()
来强制更新。但我认为在这种情况下应该自动完成。请注意,如果您想要高帧率的大图像,winforms可能还不够。您需要尽可能减少复制和分配的数量,其他较低级别的API可能更适合此目的。
我还建议从图像源创建一个抽象层,这样您就可以分别测试图像源和UI。
您还应确保正确处置所有一次性物品。