Java 调用OpenCV获取图像数据,发送Redis并从Redis获取数据显示

0、前言

项目需要读取摄像头的数据,并经过AI模型计算发送界面显示,因考虑到需要处理的摄像头过多,需要提高可移植性、通用性
目前采用 从OpenCV读取摄像头图像,发送到Redis服务器

1、jar包

commons-pool2-2.4.2.jar
jedis-2.9.0.jar
opencv-440.jar

2、RedisTes

import org.opencv.core.Mat;
import org.opencv.videoio.VideoCapture;
import org.opencv.videoio.Videoio;
import redis.clients.jedis.Jedis;

import java.awt.image.BufferedImage;
import java.util.*;
import java.util.Timer;

public class RedisTest{
    private static Jedis jedis;
    private static final String ip = "192.168.1.62";
    private BufferedImage mImg;

    static {
        jedis = new Jedis("localhost");
        System.out.println("连接成功");
        System.load("D:\\Program\\opencv\\build\\java\\x64\\opencv_java440.dll");
    }

    public static void main(String[] args) throws Exception {
        sendToRedis();
    }

    private static void sendToRedis() {
        VideoCapture capture = new VideoCapture();
        capture.open("rtsp://admin:password@" + ip + ":554/stream0");
        int height = (int) capture.get(Videoio.CAP_PROP_FRAME_HEIGHT);
        int width = (int) capture.get(Videoio.CAP_PROP_FRAME_WIDTH);
        if (height == 0 || width == 0) {
            System.out.println("camera not found!");
            return;
        }
        Mat capImg = new Mat();

        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                Jedis jedis = null;
                try {
                    capture.read(capImg);
                    if (capImg.empty()) {
                        capture.release();
                        capture.open("rtsp://admin:bjlthy123@" + ip + ":554/stream0");
                        return;
                    }
                    BufferedImage bufferedImage = Mat2BufImg.Mat2BufImg(capImg, ".jpg");
                    String imgHex = Mat2BufImg.imageToHex(bufferedImage, "jpg");
                    jedis = JedisUtil.getJedis();
                    jedis.getSet(ip, imgHex);
                    System.out.println(imgHex + "\r\n\n\n\n\n");
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    if (jedis != null) {
                        jedis.close();
                    }
                }
            }
        }, 0, 100);
    }
}

2、RedisTestShow

import redis.clients.jedis.Jedis;

import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.Timer;
import java.util.TimerTask;

public class RedisTestShow extends JPanel {
    private static Jedis jedis;
    private static final String ip = "192.168.1.62";
    private BufferedImage mImg;

    static {
        jedis = new Jedis("localhost");
        System.out.println("连接成功");
        System.load("D:\\Program\\opencv\\build\\java\\x64\\opencv_java440.dll");
    }

    public static void main(String[] args) throws Exception {
        getFromRedis();
    }

    private static void getFromRedis() {
        //Java窗口容器
        JFrame frame = new JFrame("camera");
        frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
        //Java画板容器
        RedisTestShow panel = new RedisTestShow();
        //配置关系
        frame.setContentPane(panel);
        frame.setVisible(true);
        frame.setSize(1280 + frame.getInsets().left + frame.getInsets().right, 720 + frame.getInsets().top + frame.getInsets().bottom);

        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                try {
                    String imgHex = jedis.get(ip);
                    BufferedImage bufferedImage = Mat2BufImg.hexToImage(imgHex);
                    panel.mImg = bufferedImage;
                    panel.repaint();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }, 0, 100);
    }

    @Override
    public void paintComponent(Graphics g) {
        if (mImg != null) {
            g.drawImage(mImg, 0, 0, mImg.getWidth(), mImg.getHeight(), this);
        }
    }
}

3、Mat2BufImg

import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.MatOfByte;
import org.opencv.imgcodecs.Imgcodecs;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;
import java.util.List;

public class Mat2BufImg {

    /**
     * Mat转换成BufferedImage
     *
     * @param matrix        要转换的Mat
     * @param fileExtension 格式为 ".jpg", ".png", etc
     * @return
     */
    public static BufferedImage Mat2BufImg(Mat matrix, String fileExtension) {
        // convert the matrix into a matrix of bytes appropriate for
        // this file extension
        MatOfByte mob = new MatOfByte();
        Imgcodecs.imencode(fileExtension, matrix, mob);
        // convert the "matrix of bytes" into a byte array
        byte[] byteArray = mob.toArray();
        BufferedImage bufImage = null;
        try {
            InputStream in = new ByteArrayInputStream(byteArray);
            bufImage = ImageIO.read(in);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return bufImage;
    }

    /**
     * BufferedImage转换成Mat
     *
     * @param original 要转换的BufferedImage
     * @param imgType  bufferedImage的类型 如 BufferedImage.TYPE_3BYTE_BGR
     * @param matType  转换成mat的type 如 CvType.CV_8UC3
     */
    public static Mat BufImg2Mat(BufferedImage original, int imgType, int matType) {
        if (original == null) {
            throw new IllegalArgumentException("original == null");
        }

        // Don't convert if it already has correct type
        if (original.getType() != imgType) {

            // Create a buffered image
            BufferedImage image = new BufferedImage(original.getWidth(), original.getHeight(), imgType);

            // Draw the image onto the new buffer
            Graphics2D g = image.createGraphics();
            try {
                g.setComposite(AlphaComposite.Src);
                g.drawImage(original, 0, 0, null);
            } finally {
                g.dispose();
            }
        }

        byte[] pixels = ((DataBufferByte) original.getRaster().getDataBuffer()).getData();
        Mat mat = Mat.eye(original.getHeight(), original.getWidth(), matType);
        mat.put(0, 0, pixels);
        return mat;
    }

    /**
     * 将图片转换成十六进制字符串
     *
     * @param bufferedImage BufferedImage图片流
     * @param format        参数format表示图片的格式,比如jpg等
     */
    public static String imageToHex(BufferedImage bufferedImage, String format) {
        try {
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            ImageIO.write(bufferedImage, format, outputStream);
            byte[] bytes = outputStream.toByteArray();
            return HexUtils.bytes2Hex(bytes);
            // return new BigInteger(1, bytes).toString(16);
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    public static BufferedImage hexToImage(String hex) {
        try {
            byte[] bytes = HexUtils.hex2Bytes(hex);
            ByteArrayInputStream in = new ByteArrayInputStream(bytes);
            BufferedImage image = ImageIO.read(in);
            return image;
        } catch (Exception e) {
            return null;
        }
    }


    public static byte[] matToByte(Mat mat) {
        // Mat grayMatData = new Mat();
        // cvtColor(rgbData,grayMatData,COLOR_RGB2GRAY);
        byte[] grayData = new byte[mat.cols() * mat.rows()];
        mat.get(0, 0, grayData);
        return grayData;
    }

    public static Mat vector_uchar_to_Mat(List<Byte> bs) {
        Mat res;
        int count = (bs != null) ? bs.size() : 0;
        if (count > 0) {
            res = new Mat(count, 1, CvType.CV_8UC1);
            byte[] buff = new byte[count];
            for (int i = 0; i < count; i++) {
                byte b = bs.get(i);
                buff[i] = b;
            }
            res.put(0, 0, buff);
        } else {
            res = new Mat();
        }
        return res;
    }

    // Convert image to Mat
    public Mat matify(BufferedImage bufferedImage) {
        // Convert INT to BYTE
        //im = new BufferedImage(im.getWidth(), im.getHeight(),BufferedImage.TYPE_3BYTE_BGR);
        // Convert bufferedimage to byte array
        byte[] pixels = ((DataBufferByte) bufferedImage.getRaster().getDataBuffer()).getData();
        // Create a Matrix the same size of image
        Mat mat = new Mat(bufferedImage.getHeight(), bufferedImage.getWidth(), CvType.CV_8UC3);
        // Fill Matrix with image values
        mat.put(0, 0, pixels);
        return mat;
    }
}

4、JedisUtil

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

public final class JedisUtil {
    private JedisUtil() {
    }

    private static JedisPool jedisPool;
    private static int maxtotal = 1000;
    private static int maxwaitmillis = 100;
    private static String host = "127.0.0.1";
    private static int port = 6379;

    /*读取jedis.properties配置文件*/
    static {
        // ResourceBundle rb = ResourceBundle.getBundle("jedis");
        // maxtotal = Integer.parseInt(rb.getString("maxtotal"));
        // maxwaitmillis = Integer.parseInt(rb.getString("maxwaitmillis"));
        // host = rb.getString("host");
        // port = Integer.parseInt(rb.getString("port"));
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        jedisPoolConfig.setMaxTotal(maxtotal);
        jedisPoolConfig.setMaxWaitMillis(maxwaitmillis);
        jedisPool = new JedisPool(jedisPoolConfig, host, port);
    }

    /*获取jedis*/
    public static Jedis getJedis() {
        return jedisPool.getResource();
    }

    /*关闭Jedis*/
    public static void close(Jedis jedis) {
        if (jedis != null) {
            jedis.shutdown();
        }
    }
}

5、HexUtils

/**
 * 16进制字符串 与 byte数组 相互转换工具类
 */
public class HexUtils {

    private static final char[] HEXES = {
            '0', '1', '2', '3',
            '4', '5', '6', '7',
            '8', '9', 'a', 'b',
            'c', 'd', 'e', 'f'
    };

    /**
     * byte数组 转换成 16进制小写字符串
     */
    public static String bytes2Hex(byte[] bytes) {
        if (bytes == null || bytes.length == 0) {
            return null;
        }

        StringBuilder hex = new StringBuilder();

        for (byte b : bytes) {
            hex.append(HEXES[(b >> 4) & 0x0F]);
            hex.append(HEXES[b & 0x0F]);
        }

        return hex.toString();
    }

    /**
     * 16进制字符串 转换为对应的 byte数组
     */
    public static byte[] hex2Bytes(String hex) {
        if (hex == null || hex.length() == 0) {
            return null;
        }

        char[] hexChars = hex.toCharArray();
        byte[] bytes = new byte[hexChars.length / 2];   // 如果 hex 中的字符不是偶数个, 则忽略最后一个

        for (int i = 0; i < bytes.length; i++) {
            bytes[i] = (byte) Integer.parseInt("" + hexChars[i * 2] + hexChars[i * 2 + 1], 16);
        }

        return bytes;
    }

}
posted @ 2021-03-17 11:11  一只桔子2233  阅读(505)  评论(0编辑  收藏  举报