Java 连续图像加载/处理&;单击按钮时显示(在Swing中)
我无法在Swing中连续加载、处理和显示图像: 下面是一个简单的例子,单击一个按钮会导致我的程序从网络摄像头抓取帧,然后在jlabel中显示此图片。它可以正常工作,但我必须连续单击这个“开始”按钮才能显示新的图像(帧) 我的要求更高,我想在现场视频流中进行一些图像处理,因此我需要不断地“抓取”和“显示”我的帧。您可能会说我可以启动网络摄像头流,但这不是我想要实现的,因为我将要实现一些thresholding/etc.功能,这些功能将动态修改我的图像。因此,我需要尽可能快地执行抓取、处理和显示(延迟是不允许的,因为我希望实现10 fps的速度,包括图像处理)。尽管我拖延时间是完全不受欢迎的,但我还是试着做了一些工作 下面显示的Simple while(true)/*不起作用,我的程序“挂起”,甚至不显示单个帧,尽管在调试器中它一直在反复工作Java 连续图像加载/处理&;单击按钮时显示(在Swing中),java,image,swing,processing,swingworker,Java,Image,Swing,Processing,Swingworker,我无法在Swing中连续加载、处理和显示图像: 下面是一个简单的例子,单击一个按钮会导致我的程序从网络摄像头抓取帧,然后在jlabel中显示此图片。它可以正常工作,但我必须连续单击这个“开始”按钮才能显示新的图像(帧) 我的要求更高,我想在现场视频流中进行一些图像处理,因此我需要不断地“抓取”和“显示”我的帧。您可能会说我可以启动网络摄像头流,但这不是我想要实现的,因为我将要实现一些thresholding/etc.功能,这些功能将动态修改我的图像。因此,我需要尽可能快地执行抓取、处理和显示(延
private void StartActionPerformed(java.awt.event.ActionEvent evt) {
while(true){
displayed_img = this.getPIC_COLOR(player);
//threshholding & further processing...
img_field.setIcon(new ImageIcon(displayed_img));
}
}
为了防止需要getPIC_COLOR(),我将其粘贴到下面:
public BufferedImage getPIC_COLOR(Player player){
FrameGrabbingControl frameGrabber = (FrameGrabbingControl)player.getControl("javax.media.control.FrameGrabbingControl");
Buffer buf = frameGrabber.grabFrame();
Image img = (new BufferToImage((VideoFormat)buf.getFormat()).createImage(buf));
BufferedImage buffImg = new BufferedImage(img.getWidth(null), img.getHeight(null), BufferedImage.TYPE_INT_RGB);
Graphics2D g = buffImg.createGraphics();
g.drawImage(img, null, null);
return buffImg;
}
非常感谢您的帮助
好的,读了一些书之后,我写了一些SwingWorker代码:
private void SingleFrameActionPerformed(java.awt.event.ActionEvent evt) {
SwingWorker<Void, BufferedImage> worker = new SwingWorker<Void, BufferedImage>() {
@Override
protected Void doInBackground() {
while (!isCancelled()) {
displayed_img = getPIC_COLOR(player);
publish(displayed_img);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
break;
}
}
return null;
}
@Override
protected void process(List mystuff) {
Iterator it = mystuff.iterator();
while (it.hasNext()) {
img_field.setIcon(new ImageIcon(displayed_img));
try {
ImageIO.write(displayed_img, "png", new File("c:\\testimg.jpg"));
} catch (IOException ex) {
Logger.getLogger(TestCAMGUI.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
@Override
protected void done() {
infoBAR.setText("FINISHED");
}
};
worker.execute();
private void SingleFrameActionPerformed(java.awt.event.ActionEvent evt){
SwingWorker worker=新SwingWorker(){
@凌驾
受保护的Void doInBackground(){
而(!isCancelled()){
显示的\u img=getPIC\u颜色(播放器);
发布(显示);
试一试{
睡眠(1000);
}捕捉(中断异常e){
打破
}
}
返回null;
}
@凌驾
受保护的无效进程(列表mystuff){
迭代器it=mystuff.Iterator();
而(it.hasNext()){
img_field.setIcon(新图像图标(显示的img));
试一试{
ImageIO.write(显示为“png”,新文件(“c:\\testimg.jpg”);
}捕获(IOEX异常){
Logger.getLogger(TestCAMGUI.class.getName()).log(Level.SEVERE,null,ex);
}
}
}
@凌驾
受保护的void done(){
infoBAR.setText(“完成”);
}
};
worker.execute();
}
现在,让我感到严重困扰的是,我的img_字段
没有在swing中更新,尽管ImageIO.write
在过程
中有效,并且图像在C:\上以疯狂的速度“重新绘制”(疯狂的速度是非常可取的)。此外,我的GUI仍然冻结,即使我创建了这个swing worker线程
顺便说一句,我还试图“睡眠”这一保存线程一秒钟,但我的GUI挂起,即使有这种额外的睡眠
下面是关于我的代码的一些解释:
返回void,因为我不需要返回任何内容,因为我假设此进程将一直运行到取消为止(除非程序关闭,否则这不太可能发生)doInBackground()
- 在
中,我在process()
只是为了确保我的线程启动并正常工作ImageIO中加入了try/catch块。write
- 我没有使用“SwingUtilities.invokeLater”,因为我阅读了浏览指南/教程,在我的案例中使用SwingWorker更好
- 还有什么困扰着我:在
我操作的列表会放大。。。我不需要它,我只需要一个元素就可以了。那么有没有一种方法可以从过程中
收集单个对象呢?列清单对我来说似乎是浪费记忆。或者我应该doInBackground()
清除clear()
?(以减少分配的内存)process()末尾的列表。
任何进一步的提示都非常感谢。您不能在从事件调用的方法中运行任何形式的无限循环(除非您明确地打算挂起您的用户界面,至少可以说这很奇怪)
您应该在一个单独的线程中运行frame grab,然后使用类似的方式来显示它。您的代码是多线程的吗?在Swing事件调度线程中运行无限while循环肯定是不健康的。嗯,不,它不是,我最初考虑的是多线程,但这个字段我一无所知(因此我没有参与这种高级编程),显然在这种情况下它是强制性的,对吗?尽管如此,我只想执行这个框架gram+进程+显示结果,所以我认为没有必要,尽管在我启动网络摄像头流之前,您需要知道“很少”行,但我猜它可能会对我的无限循环产生一些影响?您基本上需要了解多线程来执行Swing。某些方法必须在Swing事件调度线程(EDT)上运行,而其他方法不得在EDT上运行。在您的情况下,
setIcon
必须在EDT上运行,因为它修改了Swing组件,但是while循环必须在另一个线程上(这是可能的)。我不知道javax.media,所以我不确定getPIC\u COLOR
是否应该在EDT上运行。感谢您提供有用的提示,我想我必须参与多线程的工作;)@Marian这里有一些反产品步骤,请阅读,左侧是相关线程,以及JButton、SwingWorker的单独操作,将图像/图标保存到单独的viod,类…好的,谢谢帮助,我想我必须浏览一些多线程指南/教程来进一步了解这件事。
private void SingleFrameActionPerformed(java.awt.event.ActionEvent evt) {
SwingWorker<Void, BufferedImage> worker = new SwingWorker<Void, BufferedImage>() {
@Override
protected Void doInBackground() {
while (!isCancelled()) {
displayed_img = getPIC_COLOR(player);
publish(displayed_img);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
break;
}
}
return null;
}
@Override
protected void process(List mystuff) {
Iterator it = mystuff.iterator();
while (it.hasNext()) {
img_field.setIcon(new ImageIcon(displayed_img));
try {
ImageIO.write(displayed_img, "png", new File("c:\\testimg.jpg"));
} catch (IOException ex) {
Logger.getLogger(TestCAMGUI.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
@Override
protected void done() {
infoBAR.setText("FINISHED");
}
};
worker.execute();