连续图像加载/处理&单击按钮时显示(在Swing中) [英] Continuous image loading/processing & display on button click (in Swing)

查看:92
本文介绍了连续图像加载/处理&单击按钮时显示(在Swing中)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在Swing中连续图像加载和处理以及显示时遇到问题:

I have trouble with continuous image loading&processing&display in Swing:

下面有一个简单的例子,单击按钮会导致我的程序从网络摄像头抓取帧然后在jlabel中显示这张图片。它应该工作,但我必须连续点击这个开始按钮,以获得显示的新图像(帧)。

Below there is simple case where clicking a button causes my program to grab frame from webcam and then display this picture in jlabel. It works as it should, but i have to consecutively click this "Start" button in order to get new image(frame) shown.

private void StartActionPerformed(java.awt.event.ActionEvent evt) {                                      
           displayed_img = this.getPIC_COLOR(player);       
           img_field.setIcon(new ImageIcon(displayed_img));
        }

我要求更高,我想在实时视频流中进行一些图像处理因此,我需要抓住& 持续显示我的画面。您可能会说我可以启动网络摄像头流,但这不是我想要实现的,因为我即将实现一些阈值/等。功能将在运行中修改我的图像。因此,我需要尽可能快地执行此抓取和处理和显示(延迟是禁忌,因为我想实现类似10 fps的内容,包括图像处理)。尽管我的延迟绝对是不可取的,但我试图制作一些Thread.sleep但是它没有用。

Im more demanding and i would like to make some image processing during live video stream, therefore i need to "grab" & "show" my frames continuously. You might say that i can just launch webcam stream, but it is not what i want to achieve since i'm about to implement some threshholding/etc. functions which will modify my image on-fly. Therefore i need to perform this grabbing&processin&display as fast as possible (delay is a no-no since i want to achieve something like 10 fps including image processing). Despite the fact that i delay is utterly undesirable i tried to make some Thread.sleep however it didnt work.

简单而while(true)/ *低于* /不会工作,我的程序挂起,甚至没有显示单帧,虽然在调试器中它一直在反复工作。

Simple while(true) /* presented below */ does not work, my program "hangs" and not even single frame is displayed, although in debugger it keeps working over and over.

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(),我粘贴它在下面:

just in case getPIC_COLOR() was required, i paste it below:

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代码:

Ok, after some reading i managed to write some SwingWorker Code:

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();

}

现在严重困扰我的是什么事实是我的 img_field 没有在摇摆中更新,尽管在中存在 ImageIO.write 进程工作,图像在C:\上重新绘制,具有MAD速度(非常需要疯狂速度)。此外,即使我创建了这个摇摆工作线程,我的GUI仍然被冻结...

Now what seriously bothers me is the fact that my img_field is not updated in swing, although ImageIO.write present in process works, and image is "redrawn" on C:\ with MAD speed ("mad speed" is highly desirable). Moreover my GUI is still frozen even though i created this swing worker thread...

btw我也尝试暂停这个保存线程一秒钟,但是我的GUI即使有额外的睡眠也会挂起

btw i also tried to "sleep" this saving thread for a second, however my GUI hangs even with this additional sleep

现在我的代码有一些解释:

Now some explanations about my code:


  • doInBackground()返回void,因为我不需要返回任何内容,因为我假设此过程将一直运行直到取消(除非程序关闭,否则不太可能发生)。 / li>
  • process()我已经包含了带有的I​​mage /.crite 只是为了确保我的线程启动并运行

  • 我没有使用'SwingUtilities.invokeLater',因为浏览指南/教程我已经读过最好使用SwingWorker我的情况

  • 进一步困扰我的是:在进程我操作列表放大......我不需要,我只需要单个元素,就是全部。那么有没有办法从 doInBackground()收集单个对象?制作名单对我来说似乎是浪费。或者我应该 clear() process()结尾的列表? (为了减少分配的内存)

  • doInBackground() returns void, as i dont need to return anything, since i assume this process will run till cancelled (which is unlikely to happen, unless program is closed).
  • inside process() i've included try/catch block with ImageIO.write just to make sure my thread launched and works
  • i didnt use 'SwingUtilities.invokeLater' due to fact that browsing guides/tutorials i've read that it is better to use SwingWorker in my case
  • What bothers me furthermore: in process i operate on list which enlarges... i dont need that, i just need a single element and thats all. So is there a way to collect single object from doInBackground()? making list seems memory waste for me. Or maybe i should clear() the list at the end of process()? (in order to reduce memory allocated)

任何进一步的提示都表示赞赏。

Any further hints are appreciated.

推荐答案

你不能在从事件中调用的方法中运行该形式的任何类型的无限循环(除非你明确打算挂起你的用户界面,这很奇怪)至少)。

You must not run any kind of infinite loop of that form in a method that is called from an event (unless you explicitly intend to hang your user interface, which would be odd to say the least).

你应该在一个单独的线程中运行你的帧抓取,然后使用类似 SwingUtilities.invokeLater 显示它。

You should run your frame grab in a separate thread, and then use something like SwingUtilities.invokeLater to display it.

这篇关于连续图像加载/处理&amp;单击按钮时显示(在Swing中)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆