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;
}
}