我用javaCV抓取网络摄像头的数据,网上大多数都用的CanvasFrame的showImage来显示,但由于我的程序需要定制功能,CanvasFrame很多东西都写死了,所以我还是选择用JLabel。
大概的代码如下,其中通过调试,我发现while循环内,
inputImg = converter.getBufferedImage(frame);
label.setIcon(new ImageIcon(inputImg));
inputImg图像都已经取到值,并成功赋值给了label的Icon,可是画面始终显示不出来
我也尝试过用label.setImage(inputImg);
label.repaint();可画面还是显示不出来。。代码如下:
点击一个button,新建一个javaCV的grabber:
bWebCamera.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                imagesFrame.clearFrame();
                BufferedImage inputImg = null;                //注意下面的连接部分,用户名:密码(账号密码),
                //@符号之后的是局域网ip地址(打开app后,点击下方“打开IP摄像头服务器”,会有显示局域网ip)
                //即:http://<USERNAME>:<PASSWORD>@<IP_ADDRESS>/<the value of src>
                //<USERNAME>:<PASSWORD>通常采用HTTP基本认证(Basic Authentication)
                String ip = JOptionPane.showInputDialog("请输入网络摄像头IP:");
                String url = "http://admin:admin@" + ip;
                if (ip != null && !ip.equals("")) {
                    try {
                        //IPCameraFrameGrabber grabber = new IPCameraFrameGrabber(url, 30, 30, TimeUnit.SECONDS);
                        FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(url);
                        grabber.setOption("http", "tcp"); // 使用tcp的方式,不然会丢包很严重
                        grabber.setImageWidth(LABEL_WIDTH);
                        grabber.setImageHeight(LABEL_HEIGHT);
                        grabber.start();
                        inputImg = showFrames("网络摄像头", grabber, lc);
                        grabber.stop();
                        grabber.close();
                    } catch (FrameGrabber.Exception | InterruptedException e1) {
                        e1.printStackTrace();
                        JOptionPane.showMessageDialog(
                                imagesFrame,
                                e1.getMessage(),
                                "错误",
                                JOptionPane.ERROR_MESSAGE
                        );
                    }
                    if (inputImg != null) {
                        if (findCircle(inputImg, imagesFrame, countText)) {
                            ImageIcon icon = new ImageIcon(originalImg);
                            lc.setIcon(icon);
                            lb.setIcon(icon);
                            checkBoxListener.updateValues();
                        } else {
                            imagesFrame.clearFrame();
                            lc.setIcon(icon);
                            lb.setIcon(icon);
                        }
                    } else {
                        JOptionPane.showMessageDialog(
                                imagesFrame,
                                "没有打开图片",
                                "错误",
                                JOptionPane.ERROR_MESSAGE
                        );
                    }
                }
            }
        });显示图像的函数:
private BufferedImage showFrames(String winTitle, FrameGrabber grabber, PointRoiLabel label) throws FrameGrabber.Exception, InterruptedException {
        org.bytedeco.javacv.Frame frame = null;
        BufferedImage inputImg = null;
        Java2DFrameConverter converter = new Java2DFrameConverter();
        while ((frame = grabber.grab()) != null) {
            inputImg = converter.getBufferedImage(frame);
            label.setIcon(new ImageIcon(inputImg));
            //label.setImage(inputImg);
            //label.repaint();
            Thread.sleep(30);//30毫秒刷新一次图像
        }
        return inputImg;
    }我设计的JLabel:
package pers.frames;import ij.gui.PointRoi;import javax.swing.*;
import java.awt.*;public class PointRoiLabel extends JLabel {
    private static final int LABEL_WIDTH = 700, LABEL_HEIGHT = 540;
    PointRoi pointRoi = null;
    Image img = null;    public Image getImage() {
        return img;
    }    public void setImage(Image img) {
        this.img = img;
    }    public void setPointRoi(PointRoi pointRoi) {
        this.pointRoi = pointRoi;
    }    public PointRoi getPointRoi() {
        return pointRoi;
    }    public int getCount() {
        return pointRoi.getContainedPoints().length;
    }    @Override
    public void paint(Graphics g) {
        super.paint(g);
        if(pointRoi != null && img != null) {
            g.drawImage(img, 0, 0, null);
            //this.setIcon(new ImageIcon(img));
            pointRoi.draw(g);
        } else if (pointRoi == null && img != null) {
            g.drawImage(img, 0, 0, null);
        }
    }    public int chosedRoi(int x1, int x2, int y1, int y2) {
        int count = pointRoi.have(x1, x2, y1, y2);
        return count;
    }
}P.S:我确定可以用在while循环内不断刷新setIcon(new ImageIcon(img)来显示视频的,因为我的程序还有用opencv打开内置摄像头功能,是可以显示视频的,
while(fCamera){
                    camera.read(frame);   //read方法读取摄像头的当前帧
                    capture = ToolPanel.mat2BufferedImage(frame);
                    label.setIcon(new ImageIcon(capture));//转换图像格式并输出
                    try {
                        Thread.sleep(100);//线程暂停100ms
                    } catch (InterruptedException ee) {
                        // TODO Auto-generated catch block
                        ee.printStackTrace();
                    }
                }
所以现在这个程序我真的百思不得其解很急,求助大神!!!已经烦恼了3天了我这小虾米真的要跪了

解决方案 »

  1.   

    actionPerformed(ActionEvent e)里面的东东都包在一个线程类里,把需要的控件传进去,
    进入actionPerformed方法后启动线程,方法结束。
    在新的线程中处理图像。
    试一下。
      

  2.   


    感谢回复,其实我是试过的,我用opencv打开内置摄像头和usb摄像头都是单开的线程,所以我一开始也是照着写的这个网络摄像头的方法,单独写的一个线程,但是还是不行,也是取到了图片,也赋值给了label的icon,但是刷新不到画面上……还有没有其他头绪呢?