文档章节

Java基于百度AI+JavaCV+OpenCV 实现摄像头人数动态统计

小帅帅丶
 小帅帅丶
发布于 11/09 10:06
字数 1430
阅读 579
收藏 27

【Java】人流量统计-动态版之视频转图识别请访问 http://ai.baidu.com/forum/topic/show/940413

本文是基于上一篇进行迭代的。本文主要是以摄像头画面进行人流量统计。并对返回图像进行展示。需要额外了解JavaCV OpenCV swing awt等 

也许JavaCV OpenCV  不需要也可以实现效果。但是小帅丶就先用这样的方式实现了。别的方式大家就自己尝试吧

有可能显示的in out不对。请设置帧率试试。鄙人不是专业的。所以对帧率也不是很懂。以下代码加入也没有明显的变化。

grabber.setFrameRate(10);
grabber.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>

	<dependency>
		<groupId>org.bytedeco.javacpp-presets</groupId>
		<artifactId>opencv-platform</artifactId>
		<version>3.4.1-1.4.1</version>
	</dependency>
  </dependencies>
  •  需要用到的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 {
	
	static OpenCVFrameConverter.ToIplImage converter = new OpenCVFrameConverter.ToIplImage();
	//人流量统计(动态版)接口地址
	private static String BODY_TRACKING_URL="https://aip.baidubce.com/rest/2.0/image-classify/v1/body_tracking";
	
	private static String ACCESS_TOKEN ="";//接口的token
	/**
	 * 每个case的初始化信号,为true时对该case下的跟踪算法进行初始化,为false时重载该case的跟踪状态。当为false且读取不到相应case的信息时,直接重新初始化
	 * caseId=0 第一次请求  case_init=true  caseId>0 非第一次请求  case_init=false
	 */
	static int caseId = 0;
	public static void main(String[] args) throws Exception,
			InterruptedException {
		OpenCVFrameGrabber grabber = new OpenCVFrameGrabber(0);
		grabber.start(); // 开始获取摄像头数据
		CanvasFrame canvas = new CanvasFrame("人流量实时统计");// 新建一个窗口
		canvas.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		canvas.setAlwaysOnTop(true);
		int ex = 0;
		while (true) {
			if (!canvas.isDisplayable()) {// 窗口是否关闭
				grabber.stop();// 停止抓取
				System.exit(2);// 退出
				grabber.close();
			}
			// canvas.showImage(grabber.grab());//显示摄像头抓取的画面
			Java2DFrameConverter java2dFrameConverter = new Java2DFrameConverter();
			// 摄像头抓取的画面转BufferedImage
			BufferedImage bufferedImage = java2dFrameConverter.getBufferedImage(grabber.grabFrame());
			// bufferedImage 请求API接口 检测人流量
			String result = getBodyTrack(bufferedImage);
			BufferedImage bufferedImageAPI = getAPIResult(result);
			// 如果识别为空 则显示摄像头抓取的画面
			if (null == bufferedImageAPI) {
				canvas.showImage(grabber.grab());
			} else {
				// BufferedImage转IplImage
				IplImage iplImageAPI = BufImgToIplData(bufferedImageAPI);
				// 将IplImage转为Frame 并显示在窗口中
				Frame convertFrame = converter.convert(iplImageAPI);
				canvas.showImage(convertFrame);
			}
			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); 
    		
    		ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
    		ImageIO.write(bufferedImage,"jpg", baos); 
    		 byte[] imageInByte = baos.toByteArray(); 
            // Base64解码
    		for (int i = 0; i < imageInByte.length; ++i) {
    			if (imageInByte[i] < 0) {// 调整异常数据
    				imageInByte[i] += 256;
    			}
    		 }
    		 OutputStream out = new FileOutputStream("G:/testimg/xiaoshuairesult.jpg");//接口返回的渲染图
    		 out.write(imageInByte);
    		 out.flush();
    		 out.close();
    		return bufferedImage;
    	}else{
    		return null;
    	}
	}
	/**
	 * 获取接口处理结果图
	 * @param bufferedImage
	 * @return String
	 * @throws Exception
	 */
	public static String getBodyTrack(BufferedImage bufferedImage) throws Exception{
		 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
         ImageIO.write(bufferedImage,"jpg",baos); 
         byte[] imageInByte = baos.toByteArray(); 
         Encoder base64 = Base64.getEncoder();
         String imageBase64 = base64.encodeToString(imageInByte);
        // Base64解码
		for (int i = 0; i < imageInByte.length; ++i) {
			if (imageInByte[i] < 0) {// 调整异常数据
				imageInByte[i] += 256;
			}
		 }
		 // 生成jpeg图片
		 OutputStream out = new FileOutputStream("G:/testimg/xiaoshuai.jpg");// 新生成的图片
		 out.write(imageInByte);
		 out.flush();
		 out.close();
		 System.out.println("保存成功");  
		 baos.flush();       
		 baos.close();
         String access_token = ACCESS_TOKEN;
                String case_id = "2018";
         String case_init = "";
         String area = "10,10,630,10,630,470,10,469";
         String params = "";
         if(caseId==0){
        	case_init = "true";
        	params = "image=" + URLEncoder.encode(imageBase64, "utf-8")
     				+ "&dynamic=true&show=true&case_id=" + case_id
     				+ "&case_init="+case_init +"&area="+area;
         }else{
        	 case_init = "false";
        	 params = "image=" + URLEncoder.encode(imageBase64, "utf-8")
 					+ "&dynamic=true&show=true&case_id=" + case_id
 					+ "&case_init="+case_init +"&area="+area; 
         }
         //静态识别
//		 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一套就能实现统计摄像头中的人数。

© 著作权归作者所有

共有 人打赏支持
小帅帅丶

小帅帅丶

粉丝 496
博文 93
码字总数 118342
作品 2
北京
后端工程师
私信 提问
9个基于Java的搜索引擎框架

9个基于Java的搜索引擎框架 [导读] Lucene是目前最受欢迎的Java全文搜索框架,准确地说,它是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎,部分文本分析引擎。Lucene为开发人员...

引鸩怼孑
2015/07/30
0
0
亮剑JVM的9款编程语言杀手开发利器重磅推荐

随着各种各样的编程语言铺地盖地向我们涌来,软件世界似乎变得有点疯狂了。JVM的帝国在不断地壮大,它已经不满足于只作为Java语言的运行平台。它勇敢地将自己的触角伸向了JRuby,Groovy等等,...

ndjys
2012/03/19
0
0
JavaAgent-SandBox

1.前言 之前初步学习了javaAgent,并做了一份总结《JavaAgent学习笔记》。然后在看到《JVM-Sandbox 基于JVM的非侵入式运行期AOP解决方案》之后,接触到了集团的sandBox。并尝试使用这种有真正...

何度
05/09
0
0
新浪、百度、好未来3offer到手全记录 | 牛客面经

新浪、百度、好未来3offer到手全记录 牛客面经 原创 2017-09-19 牛友 招聘消息汇总 渣渣的秋招之路 附上新浪,百度,好未来面经 作者:offer快到碗里来?。! 来源:牛客网 楼主是本科渣渣,...

公子只识黛玉
04/17
0
0
使用JMF(Java Media Framework)使用电脑摄像头

JMF(Java Media Framework)是Java媒体框架,包含了许多用于处理多媒体的API可以让基于JAVA的应用实现音频、视频的捕捉、处理、播放、传输等功能。利用它,可以实现音、视频播放,网络视频聊...

BLUE-魏晓峰
2013/05/24
0
3

没有更多内容

加载失败,请刷新页面

加载更多

DataFrames中的reindex用法

from pandas import DataFrame frame = DataFrame(np.arange(9).reshape((3,3)),index=['a','c','d'],columns=['Ohio','Texas','California'] states = ['Texas','Utah','California'] frame......

卖小孩的小火柴
17分钟前
1
0
拜托!面试请不要再问我Spring Cloud底层原理

毫无疑问,Spring Cloud是目前微服务架构领域的翘楚,无数的书籍博客都在讲解这个技术。不过大多数讲解还停留在对Spring Cloud功能使用的层面,其底层的很多原理,很多人可能并不知晓。因此本...

James-
17分钟前
1
0
Shiro框架

提供了认证,授权,加密,会话管理等功能 在spring配置文件中配置shiro,需要配置的有shiro的过滤器工厂,在里面我们可以配置什么页面需要认证,什么认证不需要认证,认证成功后跳转的路径,认证失败...

tinder_boy
20分钟前
0
0
有关定时任务的表达式--cron 详细解

Cron表达式是一个字符串,字符串以5或6个空格隔开,分为6或7个域,每一个域代表一个含义,Cron有如下两种语法格式: Seconds Minutes Hours DayofMonth Month DayofWeek Year或 Seconds Minu...

kuchawyz
22分钟前
1
0
下一代大数据处理引擎,阿里云实时计算独享模式重磅发布

11月14日,阿里云重磅发布了实时计算独享模式,即用户独享一部分物理资源,这部分资源在网络/磁盘/CPU/内存等资源上跟其他用户完全独立,是实时计算在原有共享模式基础上的重大升级。 (观看...

阿里云云栖社区
22分钟前
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部