
【Java】人流量统计-动态版之视频转图识别请访问 http://ai.baidu.com/forum/topic/show/940413
本文是基于上一篇进行迭代的。本文主要是以摄像头画面进行人流量统计。并对返回图像进行展示。需要额外了解JavaCV OpenCV swing awt等
也许JavaCV OpenCV 不需要也可以实现效果。但是小帅丶就先用这样的方式实现了。别的方式大家就自己尝试吧
有可能显示的in out不对。请设置帧率试试。鄙人不是专业的。所以对帧率也不是很懂。以下代码加入也没有明显的变化。
1grabber.setFrameRate(10); 2grabber.setFrameNumber(10);
项目代码地址 https://gitee.com/xshuai/bodyTrack
-
注意的问题
1.动态识别的area参数为矩阵的4个顶点的xy坐标(即像素) 顺序是 上左下右 也就是顺时针一圈4个点的坐标点 2.case_id 为int 请不要给大于int范围的值。或非int类型的值 即正整数就行 3.area的值不要大于图片本身的宽高
-
需要用到的jar 通过maven引入(下载的jar较多。需要等待较长时间)
<properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> <ffmpeg.version>3.2.1-1.3</ffmpeg.version> <javacv.version>1.4.1</javacv.version> </properties> <dependencies> <dependency> <groupId>org.bytedeco.javacpp-presets</groupId> <artifactId>ffmpeg-platform</artifactId> <version>${ffmpeg.version}</version> </dependency> <!-- fastjson --> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.35</version> </dependency> <dependency> <groupId>org.bytedeco</groupId> <artifactId>javacv</artifactId> <version>${javacv.version}</version> </dependency>
</dependencies>1<dependency> 2 <groupId>org.bytedeco.javacpp-presets</groupId> 3 <artifactId>opencv-platform</artifactId> 4 <version>3.4.1-1.4.1</version> 5</dependency> -
需要用到的Java工具类
HttpUtil https://ai.baidu.com/file/544D677F5D4E4F17B4122FBD60DB82B3
-
调用接口示例代码(需要自己的电脑有摄像头哦)
import java.awt.image.BufferedImage; import java.awt.image.DataBufferByte; import java.awt.image.WritableRaster; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.FileOutputStream; import java.io.OutputStream; import java.net.URLEncoder; import java.util.Base64; import java.util.Base64.Decoder; import java.util.Base64.Encoder;
import javax.imageio.ImageIO; import javax.swing.JFrame;
import org.bytedeco.javacpp.BytePointer; import org.bytedeco.javacpp.opencv_core.IplImage; import org.bytedeco.javacv.CanvasFrame; import org.bytedeco.javacv.Frame; import org.bytedeco.javacv.Java2DFrameConverter; import org.bytedeco.javacv.OpenCVFrameConverter; import org.bytedeco.javacv.OpenCVFrameConverter.ToIplImage; import org.bytedeco.javacv.OpenCVFrameGrabber;
import com.alibaba.fastjson.JSONObject;
import cn.xsshome.body.util.HttpUtil; /**
- 获取摄像头画面进行处理并回显图片在画面中
- 人流量统计(动态版)JavaAPI示例代码
- @author 小帅丶
*/ public class JavavcCameraTest {
1static OpenCVFrameConverter.ToIplImage converter = new OpenCVFrameConverter.ToIplImage(); 2//人流量统计(动态版)接口地址 3private static String BODY_TRACKING_URL="https://aip.baidubce.com/rest/2.0/image-classify/v1/body_tracking"; 4 5private static String ACCESS_TOKEN ="";//接口的token 6/** 7 * 每个case的初始化信号,为true时对该case下的跟踪算法进行初始化,为false时重载该case的跟踪状态。当为false且读取不到相应case的信息时,直接重新初始化 8 * caseId=0 第一次请求 case_init=true caseId>0 非第一次请求 case_init=false 9 */ 10static int caseId = 0; 11public static void main(String[] args) throws Exception, 12 InterruptedException { 13 OpenCVFrameGrabber grabber = new OpenCVFrameGrabber(0); 14 grabber.start(); // 开始获取摄像头数据 15 CanvasFrame canvas = new CanvasFrame("人流量实时统计");// 新建一个窗口 16 canvas.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 17 canvas.setAlwaysOnTop(true); 18 int ex = 0; 19 while (true) { 20 if (!canvas.isDisplayable()) {// 窗口是否关闭 21 grabber.stop();// 停止抓取 22 System.exit(2);// 退出 23 grabber.close(); 24 } 25 // canvas.showImage(grabber.grab());//显示摄像头抓取的画面 26 Java2DFrameConverter java2dFrameConverter = new Java2DFrameConverter(); 27 // 摄像头抓取的画面转BufferedImage 28 BufferedImage bufferedImage = java2dFrameConverter.getBufferedImage(grabber.grabFrame()); 29 // bufferedImage 请求API接口 检测人流量 30 String result = getBodyTrack(bufferedImage); 31 BufferedImage bufferedImageAPI = getAPIResult(result); 32 // 如果识别为空 则显示摄像头抓取的画面 33 if (null == bufferedImageAPI) { 34 canvas.showImage(grabber.grab()); 35 } else { 36 // BufferedImage转IplImage 37 IplImage iplImageAPI = BufImgToIplData(bufferedImageAPI); 38 // 将IplImage转为Frame 并显示在窗口中 39 Frame convertFrame = converter.convert(iplImageAPI); 40 canvas.showImage(convertFrame); 41 } 42 ex++;// Thread.sleep(100);// 100毫秒刷新一次图像.因为接口返回需要时间。所以看到的画面还是会有一定的延迟 } } /** * BufferedImage转IplImage * @param bufferedImageAPI * @return / private static IplImage BufImgToIplData(BufferedImage bufferedImageAPI) { IplImage iplImage = null; ToIplImage iplConverter = new OpenCVFrameConverter.ToIplImage(); Java2DFrameConverter java2dConverter = new Java2DFrameConverter(); iplImage = iplConverter.convert(java2dConverter.convert(bufferedImageAPI)); return iplImage; } /* * IplImage 转 BufferedImage * @param mat * @return BufferedImage / public static BufferedImage iplToBufImgData(IplImage mat) { if (mat.height() > 0 && mat.width() > 0) { //TYPE_3BYTE_BGR 表示一个具有 8 位 RGB 颜色分量的图像,对应于 Windows 风格的 BGR 颜色模型,具有用 3 字节存储的 Blue、Green 和 Red 三种颜色。 BufferedImage image = new BufferedImage(mat.width(), mat.height(),BufferedImage.TYPE_3BYTE_BGR); WritableRaster raster = image.getRaster(); DataBufferByte dataBuffer = (DataBufferByte) raster.getDataBuffer(); byte[] data = dataBuffer.getData(); BytePointer bytePointer = new BytePointer(data); mat.imageData(bytePointer); return image; } return null; } /* * 接口结果转bufferimage * @param result * @return BufferedImage * @throws Exception */ private static BufferedImage getAPIResult(String result) throws Exception { JSONObject object = JSONObject.parseObject(result); BufferedImage bufferedImage = null; if(object.getInteger("person_num")>=1){ Decoder decoder = Base64.getDecoder(); byte [] b = decoder.decode(object.getString("image")); ByteArrayInputStream in = new ByteArrayInputStream(b);
bufferedImage = ImageIO.read(in);1 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 2 ImageIO.write(bufferedImage,"jpg", baos); 3 byte[] imageInByte = baos.toByteArray(); 4 // Base64解码 5 for (int i = 0; i < imageInByte.length; ++i) { 6 if (imageInByte[i] < 0) {// 调整异常数据 7 imageInByte[i] += 256; 8 } 9 } 10 OutputStream out = new FileOutputStream("G:/testimg/xiaoshuairesult.jpg");//接口返回的渲染图 11 out.write(imageInByte); 12 out.flush(); 13 out.close(); 14 return bufferedImage; 15 }else{ 16 return null; 17 } 18} 19/** 20 * 获取接口处理结果图 21 * @param bufferedImage 22 * @return String 23 * @throws Exception 24 */ 25public static String getBodyTrack(BufferedImage bufferedImage) throws Exception{ 26 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 27 ImageIO.write(bufferedImage,"jpg",baos); 28 byte[] imageInByte = baos.toByteArray(); 29 Encoder base64 = Base64.getEncoder(); 30 String imageBase64 = base64.encodeToString(imageInByte); 31 // Base64解码 32 for (int i = 0; i < imageInByte.length; ++i) { 33 if (imageInByte[i] < 0) {// 调整异常数据 34 imageInByte[i] += 256; 35 } 36 } 37 // 生成jpeg图片 38 OutputStream out = new FileOutputStream("G:/testimg/xiaoshuai.jpg");// 新生成的图片 39 out.write(imageInByte); 40 out.flush(); 41 out.close(); 42 System.out.println("保存成功"); 43 baos.flush(); 44 baos.close(); 45 String access_token = ACCESS_TOKEN; 46 String case_id = "2018"; 47 String case_init = ""; 48 String area = "10,10,630,10,630,470,10,469"; 49 String params = ""; 50 if(caseId==0){ 51 case_init = "true"; 52 params = "image=" + URLEncoder.encode(imageBase64, "utf-8") 53 + "&dynamic=true&show=true&case_id=" + case_id 54 + "&case_init="+case_init +"&area="+area; 55 }else{ 56 case_init = "false"; 57 params = "image=" + URLEncoder.encode(imageBase64, "utf-8") 58 + "&dynamic=true&show=true&case_id=" + case_id 59 + "&case_init="+case_init +"&area="+area; 60 } 61 //静态识别// String params = "image=" + URLEncoder.encode(imageBase64, "utf-8")+"&dynamic=false&show=true"; String result = HttpUtil.post(BODY_TRACKING_URL, access_token, params); System.out.println("接口内容==>"+result); return result; } /** * IplImage 转 BufferedImage * @param mat * @return BufferedImage */ public static BufferedImage bufferimgToBase64(IplImage mat) { if (mat.height() > 0 && mat.width() > 0) { BufferedImage image = new BufferedImage(mat.width(), mat.height(),BufferedImage.TYPE_3BYTE_BGR); WritableRaster raster = image.getRaster(); DataBufferByte dataBuffer = (DataBufferByte) raster.getDataBuffer(); byte[] data = dataBuffer.getData(); BytePointer bytePointer = new BytePointer(data); mat.imageData(bytePointer); return image; } return null; } }
-
摄像头中的内容截图示意(本人头像就不直接显示了。万一吓着大家呢) 也不要用去马赛克的技术还原图片哦。

还是很好玩的、不需要自己去整OpenCV一套就能实现统计摄像头中的人数。