实战物联网安防监控项目———把模拟数据传输到web网页web显示mjpeg-streamer视频图像
Posted imysy_22_
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了实战物联网安防监控项目———把模拟数据传输到web网页web显示mjpeg-streamer视频图像相关的知识,希望对你有一定的参考价值。
1、模拟数据传输到web
为了把硬件传感器上的数据上传到web网页,我们需要在跑linux服务器的开发板上写一个应用程序,并创建出几个线程来收集传感器检测到的数据,通过进程/线程间通信、boa与cgic库的知识来实现数据上传到web网页。
例程:
main.c
#include <stdio.h>
#include <pthread.h>
#include <errno.h>
#include <signal.h>
#include <unistd.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <sys/ipc.h>
#include "data_global.h"
void release_pthread_resource(int signo);
extern pthread_mutex_t mutex_client_request,
mutex_refresh,
mutex_sqlite,
mutex_transfer,
mutex_sms,
mutex_buzzer,
mutex_led;
extern pthread_cond_t cond_client_request,
cond_refresh,
cond_sqlite,
cond_transfer,
cond_transfer,
cond_sms,
cond_buzzer,
cond_led;
extern int msgid;
extern int shmid;
extern int semid;
pthread_t id_client_request,
id_refresh,
id_sqlite,
id_transfer,
id_sms,
id_buzzer,
id_led;
int main(int argc, const char *argv[])
//
pthread_mutex_init(&mutex_client_request,NULL);
pthread_mutex_init(&mutex_refresh,NULL);
pthread_mutex_init(&mutex_sqlite,NULL);
pthread_mutex_init(&mutex_transfer,NULL);
pthread_mutex_init(&mutex_sms,NULL);
pthread_mutex_init(&mutex_buzzer,NULL);
pthread_mutex_init(&mutex_led,NULL);
signal (SIGINT, release_pthread_resource);
pthread_cond_init(&cond_client_request,NULL);
pthread_cond_init(&cond_refresh,NULL);
pthread_cond_init(&cond_sqlite,NULL);
pthread_cond_init(&cond_transfer,NULL);
pthread_cond_init(&cond_sms,NULL);
pthread_cond_init(&cond_buzzer,NULL);
pthread_cond_init(&cond_led,NULL);
pthread_create(&id_client_request, NULL,pthread_client_request,NULL);
pthread_create(&id_refresh, NULL,pthread_refresh,NULL);
pthread_create(&id_sqlite, NULL,pthread_sqlite,NULL);
pthread_create(&id_transfer, NULL,pthread_transfer,NULL);
pthread_create(&id_sms, NULL,pthread_sms,NULL);
pthread_create(&id_buzzer, NULL,pthread_buzzer,NULL);
pthread_create(&id_led, NULL,pthread_led,NULL);
//
pthread_join(id_client_request,NULL); printf ("pthread1\\n");
pthread_join(id_refresh,NULL); printf ("pthread2\\n");
pthread_join(id_sqlite,NULL); printf ("pthread3\\n");
pthread_join(id_transfer,NULL); printf ("pthread4\\n");
pthread_join(id_sms,NULL); printf ("pthread5\\n");
pthread_join(id_buzzer,NULL); printf ("pthread6\\n");
pthread_join(id_led,NULL); printf ("pthread7\\n");
return 0;
void release_pthread_resource(int signo)
pthread_mutex_destroy (&mutex_client_request);
pthread_mutex_destroy (&mutex_refresh);
pthread_mutex_destroy (&mutex_sqlite);
pthread_mutex_destroy (&mutex_transfer);
pthread_mutex_destroy (&mutex_sms);
pthread_mutex_destroy (&mutex_buzzer);
pthread_mutex_destroy (&mutex_led);
pthread_cond_destroy (&cond_client_request);
pthread_cond_destroy (&cond_refresh);
pthread_cond_destroy (&cond_sqlite);
pthread_cond_destroy (&cond_transfer);
pthread_cond_destroy (&cond_sms);
pthread_cond_destroy (&cond_buzzer);
pthread_cond_destroy (&cond_led);
pthread_detach(id_client_request);
pthread_detach(id_refresh);
pthread_detach(id_sqlite);
pthread_detach(id_transfer);
pthread_detach(id_sms);
pthread_detach(id_buzzer);
pthread_detach(id_led);
printf("all pthread is detached\\n");
msgctl (msgid, IPC_RMID, NULL);
shmctl (shmid, IPC_RMID, NULL);
semctl (semid, 1, IPC_RMID, NULL);
exit(0);
pthread_client_request.c
#include "data_global.h"
extern int msgid;
extern key_t key;
extern pthread_mutex_t mutex_client_request,
mutex_refresh,
mutex_sqlite,
mutex_transfer,
mutex_analysis,
mutex_sms,
mutex_buzzer,
mutex_led,
mutex_camera;
extern pthread_cond_t cond_client_request,
cond_refresh,
cond_sqlite,
cond_transfer,
cond_analysis,
cond_sms,
cond_buzzer,
cond_led,
cond_camera;
extern char recive_phone[12] ;
extern char center_phone[12] ;
struct msg msgbuf;
//:澶勭悊娑堟伅闃熷垪閲岃姹傜殑绾跨▼.
void *pthread_client_request(void *arg)
if((key = ftok("/tmp",'g')) < 0)
perror("ftok failed .\\n");
exit(-1);
msgid = msgget(key,IPC_CREAT|IPC_EXCL|0666);
if(msgid == -1)
if(errno == EEXIST)
msgid = msgget(key,0777);
else
perror("fail to msgget");
exit(1);
printf("pthread_client_request\\n");
while(1)
bzero(&msgbuf,sizeof(msgbuf));
printf("wait form client request...\\n");
msgrcv (msgid, &msgbuf, sizeof (msgbuf) - sizeof (long), 1L, 0);
printf ("Get %ldL msg\\n", msgbuf.msgtype);
printf ("text[0] = %#x\\n", msgbuf.text[0]);
switch(msgbuf.msgtype)
case 1L:
printf("hello led\\n");
break;
case 2L:
printf("hello beep\\n");
break;
case 3L:
printf("hello seg\\n");
break;
case 4L:
printf("hello fan\\n");
break;
case 5L:
printf("set env data\\n");
printf("temMAX: %d\\n",*((int *)&msgbuf.text[1]));
printf("temMIN: %d\\n",*((int *)&msgbuf.text[5]));
printf("humMAX: %d\\n",*((int *)&msgbuf.text[9]));
printf("humMAX: %d\\n",*((int *)&msgbuf.text[13]));
printf("illMAX: %d\\n",*((int *)&msgbuf.text[17]));
printf("illMAX: %d\\n",*((int *)&msgbuf.text[21]));
break;
case 6L:
case 7L:
case 8L:
case 9L:
printf("你可以将这些作为扩展来学习,加油.\\n");
break;
case 10L:
int i = 0 , j = 0 ;
for(i = 0 ; i < 11; i++)
recive_phone[i] = msgbuf.text[i];
recive_phone[i] = '\\0';
printf("recive:%s\\n",recive_phone);
for(j = 0 ;msgbuf.text[i] != '\\0' && j < 12; i++, j++)
center_phone[j] = msgbuf.text[i];
center_phone[j] = '\\0';
printf("center:%s\\n",center_phone);
#if 0
pthread_mutex_lock (&mutex_slinklist);
sqlite_InsertLinknode (ENV_UPDATE, all_info_RT, sto_no, 0);//0,0鍒嗗埆鏄粨搴撳彿鍜岃揣鐗╃绫诲彿
pthread_mutex_unlock (&mutex_slinklist);
pthread_cond_signal (&cond_sqlite);
#endif
break;
default:
break;
#if 0
long msgtype;//具体的消息类型
消息类型的分配:
1L: LED控制
2L: 蜂鸣器控制
3L: 四路LED灯模拟的数码管
4L: 风扇
5L: 温湿度最值设置
6L-7L-8L-9L,用于个人的扩展
10L: 3G通信模块-GPRS
switch(msgbuf.msgtype)
case 1L: ... break;
....
default .... break;
#endif
pthread_refresh.c
#include "data_global.h"
#include "sem.h"
#define N 1024 //for share memory
extern int shmid;
extern int msgid;
extern int semid;
extern key_t shm_key;
extern key_t sem_key;
extern key_t key; //msg_key
extern pthread_mutex_t mutex_client_request,
mutex_refresh,
mutex_sqlite,
mutex_transfer,
mutex_analysis,
mutex_sms,
mutex_buzzer,
mutex_led,
mutex_camera;
extern pthread_cond_t cond_client_request,
cond_refresh,
cond_sqlite,
cond_transfer,
cond_analysis,
cond_sms,
cond_buzzer,
cond_led,
cond_camera;
extern struct env_info_client_addr sm_all_env_info;
struct shm_addr
char shm_status; //shm_status可以等于home_id,用来区分共享内存数据
struct env_info_client_addr sm_all_env_info;
;
struct shm_addr *shm_buf;
int file_env_info_struct(struct env_info_client_addr *rt_status,int home_id);
void *pthread_refresh(void *arg)
//semaphore for access to resource limits
if((sem_key = ftok("/tmp",'g')) < 0)
perror("ftok failed .\\n");
exit(-1);
semid = semget(sem_key,1,IPC_CREAT|IPC_EXCL|0666);
if(semid == -1)
if(errno == EEXIST)
semid = semget(sem_key,1,0777);
else
perror("fail to semget");
exit(1);
else
init_sem (semid, 0, 1);
//share memory for env_info refresh config
if((shm_key = ftok("/tmp",'g')) < 0)
perror("ftok failed .\\n");
exit(-1);
shmid = shmget(shm_key,N,IPC_CREAT|IPC_EXCL|0666);
if(shmid == -1)
if(errno == EEXIST)
shmid = shmget(key,N,0777);
else
perror("fail to shmget");
exit(1);
//share memap
if((shm_buf = (struct shm_addr *)shmat(shmid,NULL,0)) == (void *)-1)
perror("fail to shmat");
exit(1);
printf("pthread_refresh ......>>>>>>>\\n");
#if 1
bzero (shm_buf, sizeof (struct shm_addr));
while(1)
sem_p(semid,0);
shm_buf->shm_status = 1;
file_env_info_struct(&shm_buf->sm_all_env_info,shm_buf->shm_status);
sleep(1);
sem_v(semid,0);
#endif
int file_env_info_struct(struct env_info_client_addr *rt_status,int home_id)
int env_info_size = sizeof(struct env_info_client_addr);
//printf("env_info_size = %d.\\n",env_info_size);
rt_status->monitor_no[home_id].zigbee_info.temperature = 10.0;
rt_status->monitor_no[home_id].zigbee_info.tempMIN = 2.0;
rt_status->monitor_no[home_id].zigbee_info.tempMAX = 20.0;
rt_status->monitor_no[home_id].zigbee_info.humidity = 20.0;
rt_status->monitor_no[home_id].zigbee_info.humidityMIN = 10.0;
rt_status->monitor_no[home_id].zigbee_info.humidityMAX = 30.0;
rt_status->monitor_no[home_id].zigbee_info.reserved[0] = 0.01;
rt_status->monitor_no[home_id].zigbee_info.reserved[1] = -0.01;
rt_status->monitor_no[home_id].a9_info.adc = 9.0;
rt_status->monitor_no[home_id].a9_info.gyrox = -14.0;
rt_status->monitor_no[home_id].a9_info.gyroy = 20.0;
rt_status->monitor_no[home_id].a9_info.gyroz = 40.0;
rt_status->monitor_no[home_id].a9_info.aacx = 642.0;
rt_status->monitor_no[home_id].a9_info.aacy = -34.0;
rt_status->monitor_no[home_id].a9_info.aacz = 5002.0;
rt_status->monitor_no[home_id].a9_info.reserved[0] = 0.01;
rt_status->monitor_no[home_id].a9_info.reserved[1] = -0.01;
return 0;
通过Makefile 编译链接出一个可执行程序 monitor_obj
CROSS_COMPILE=arm-linux-
CC=$(CROSS_COMPILE)gcc
CFLAGS= -c -g
#LDFLAGS= -lpthread -L ./lib -lsqlite3
LDFLAGS= -lpthread
OBJS=main.o data_global.o pthread_transfer.o \\
pthread_client_request.o pthread_buzzer.o pthread_led.o\\
pthread_sqlite.o \\
pthread_refresh.o pthread_sms.o
monitor_obj :$(OBJS)
$(CC) -o $@ $^ $(LDFLAGS)
mv *o ./obj
$(OBJS):%.o:%.c
$(CC) $(CFLAGS) $< -o $@
install:
sudo cp monitor_obj ~/source/rootfs/
.PHONY:clean
clean:
rm *.o monitor_obj -rf
在开发板上运行此程序
(&的意义: 这里需要后台运行 如果不后台运行命令行就会一直停留在此程序)
在Ubuntu上打开制定的网页便会输出一下信息
网页的搭建很简单,主要是在html的<body>中添加一个<table>
<table width="1080" height="511" border="1" align="center">
<tr>
<td width="283" height="500" background="./images/zigee.jpg" align="left"></td>
<td width="432"><iframe src="cgi-bin/env1.cgi" height="500" width="518" align="middle"></iframe></td>
<td width="283" background="./images/gprs.jpg" align="right"></td>
</tr>
</table>
而这个env1.cgi是源文件env1.c生成
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <string.h>
#include <errno.h>
#include <sys/sem.h>
#include <unistd.h>
#include "sem.h"
#include "cgic.h"
#include "data_global.h"
#define N 32
#define MONITOR_NUM 1
char status[2][6] = "Close", "Open";
char fan_status[4][6] = "Close", "One", "Two", "Three";
struct shm_addr
char shm_status;
struct env_info_client_addr sm_all_env_info;
;
int cgiMain()
key_t key;
int shmid,semid;
struct shm_addr *shm_buf;
if((key = ftok("/tmp",'i')) <0)
perror("ftok");
exit(1);
printf("key = %x\\n",key);
if((semid = semget(key, 1, 0666)) < 0)
perror("semget");
exit(1);
if((shmid = shmget(key, N, 0666 )) == -1)
perror("shmget");
exit(1);
if((shm_buf = (struct shm_addr*)shmat(shmid, NULL, 0)) == (void*)-1 )
perror("shmat");
exit(1);
sem_p(semid,0);
cgiHeaderContentType("text/html");
fprintf(cgiOut, "<head><meta http-equiv=\\"refresh\\" content=\\"1\\"><style><!--bodyline-height:50%--></style> </head>");
fprintf(cgiOut, "<HTML>\\n");
fprintf(cgiOut, "<BODY bgcolor=\\"#666666\\">\\n");
//fprintf(cgiOut, "<h1><font color=\\"#FF0000\\">HOME_ID #%d:</font></H2>\\n ", shm_buf->shm_status);
if (shm_buf->shm_status == 1)
fprintf(cgiOut, "<script>function show()var date =new Date(); var now = \\"\\"; now = date.getFullYear()+\\"年\\"; now = now + (date.getMonth()+1)+\\"月\\"; \\ now = now + date.getDate()+\\"日\\"; now = now + date.getHours()+\\"时\\"; now = now + date.getMinutes()+\\"分\\";now = now + date.getSeconds()+\\"秒\\"; document.getElementById(\\"nowDiv\\").innerHTML = now; setTimeout(\\"show()\\",1000); </script> \\n ");
fprintf(cgiOut, "<h2><font face=\\"Broadway\\"><font color=\\"#00FAF0\\">Home1 Real-time Environment Info:</font></font></H2>\\n ");
fprintf(cgiOut, "<h2 align=center><font color=\\"#cc0033\\"><body onload=\\"show()\\"> <div id=\\"nowDiv\\"></div></font></h2> \\n ");
fprintf(cgiOut, "<h4>ZIGBEE数据显示部分</H4>\\n ");
fprintf(cgiOut, "<h4>Temperature:\\t%0.2f</H4>\\n ", shm_buf->sm_all_env_info.monitor_no[shm_buf->shm_status].zigbee_info.temperature );
fprintf(cgiOut, "<h4>Humidity:\\t%0.2f</H4>\\n ", shm_buf->sm_all_env_info.monitor_no[shm_buf->shm_status].zigbee_info.humidity);
fprintf(cgiOut, "<h4>A9数据显示部分</H4>\\n ");
fprintf(cgiOut, "<h4>Adc:\\t%0.2f</H4>\\n ", shm_buf->sm_all_env_info.monitor_no[shm_buf->shm_status].a9_info.adc);
fprintf(cgiOut, "<h4>GYROX:\\t%d</H4>\\n ", shm_buf->sm_all_env_info.monitor_no[shm_buf->shm_status].a9_info.gyrox);
fprintf(cgiOut, "<h4>GYROY:\\t%d</H4>\\n ", shm_buf->sm_all_env_info.monitor_no[shm_buf->shm_status].a9_info.gyroy);
fprintf(cgiOut, "<h4>GYROZ:\\t%d</H4>\\n ", shm_buf->sm_all_env_info.monitor_no[shm_buf->shm_status].a9_info.gyroz);
fprintf(cgiOut, "<h4>AACX :\\t%d</H4>\\n ", shm_buf->sm_all_env_info.monitor_no[shm_buf->shm_status].a9_info.aacx);
fprintf(cgiOut, "<h4>AACY :\\t%d</H4>\\n ", shm_buf->sm_all_env_info.monitor_no[shm_buf->shm_status].a9_info.aacy);
fprintf(cgiOut, "<h4>AACZ :\\t%d</H4>\\n ", shm_buf->sm_all_env_info.monitor_no[shm_buf->shm_status].a9_info.aacz);
fprintf(cgiOut, "<h4>A9-RESERVED[0]:\\t%d</H4>\\n ", shm_buf->sm_all_env_info.monitor_no[shm_buf->shm_status].a9_info.reserved[0]);
fprintf(cgiOut, "<h4>A9-RESERVED[1]:\\t%d</H4>\\n ", shm_buf->sm_all_env_info.monitor_no[shm_buf->shm_status].a9_info.reserved[1]);
fprintf(cgiOut, "<h4>STM32数据显示部分</H4>\\n ");
fprintf(cgiOut, "<h4>......</H4>\\n ");
else
fprintf(cgiOut, "<h2><font face=\\"Broadway\\"><font color=\\"#FFFAF0\\">Close!</font></font></H2>\\n ");
// fprintf(cgiOut, "<h3>:</H3>\\n ");
fprintf(cgiOut, "</BODY></HTML>\\n");
sem_v (semid, 0);
return 0;
把这个env1.html放在boa下的www目录下,env1.cgi放在cgi-bin目录下即可
2、web显示mjpeg-streamer视频图像
这部分过程比较艰难,学完后我摆烂了一天打了一整天游戏抚慰了我艰辛的心灵哈哈哈。
①驱动移植
因为要使用摄像头这个硬件,肯定要避免不了操作linux内核,驱动移植、以及设备树修改。
1. 修改设备树文件
vim arch/arm/boot/dts/exynos4412-fs4412.dts
添加如下内容:
usbphy: usbphy@125B0000
#address-cells = <1>;
#size-cells = <1>;
compatible = "samsung,exynos4x12-usb2phy";
reg = <0x125B0000 0x100>;
ranges;
clocks = <&clock 2>, <&clock 305>;
clock-names = "xusbxti", "otg";
usbphy-sys
reg = <0x10020704 0x8 0x1001021c 0x4>;
;
;
ehci@12580000
status = "okay";
usbphy = <&usbphy>;
;
usb3503@08
compatible = "smsc,usb3503";
reg = <0x08 0x4>;
connect-gpios = <&gpm3 3 1>;
intn-gpios = <&gpx2 3 1>;
reset-gpios = <&gpm2 4 1>;
initial-mode = <1>;
;
2. 配置内核
make menuconfig
3. 编译内核和设备树
$ make uImage
$ make dtbs
4. 测试:
拷贝内核和设备树文件到/tftpboot 目录下
$ cp arch/arm/boot/uImage /tftpboot
$ cp arch/arm/boot/dts/exynos4412-fs4412.dtb /tftpboot/
启动目标板并在目标板上完成如下操作:
插入U 盘显示如下
[ 72.695000] usb 1-3.2: USB disconnect, device number 3
[ 74.435000] usb 1-3.2: new high-speed USB device number 4 using exynos-ehci
[ 74.555000] usb-storage 1-3.2:1.0: USB Mass Storage device detected
[ 74.560000] scsi1 : usb-storage 1-3.2:1.0
[ 75.645000] scsi 1:0:0:0: Direct-Access Kingston DataTraveler 160 PMAP PQ: 0
ANSI: 4
[ 75.660000] sd 1:0:0:0: Attached scsi generic sg0 type 0
[ 76.695000] sd 1:0:0:0: [sda] 15556608 512-byte logical blocks: (7.96 GB/7.41 GiB)
[ 76.700000] sd 1:0:0:0: [sda] Write Protect is off
[ 76.705000] sd 1:0:0:0: [sda] No Caching mode page found
[ 76.710000] sd 1:0:0:0: [sda] Assuming drive cache: write through
[ 76.725000] sd 1:0:0:0: [sda] No Caching mode page found
[ 76.730000] sd 1:0:0:0: [sda] Assuming drive cache: write through
[ 76.760000] sda: sda1 (sda 是设备名 sda1 是分区名)
[ 76.770000] sd 1:0:0:0: [sda] No Caching mode page found
[ 76.770000] sd 1:0:0:0: [sda] Assuming drive cache: write through
[ 76.780000] sd 1:0:0:0: [sda] Attached SCSI removable disk
在终端上执行挂载的设备与上边显示相关
# mount -t vfat /dev/sda1 /mnt
# ls
可以查看到U 盘内容,即大功告成!!!
3、mjpg-stream的移植
关于mjpg-stream的资料大家可以在下面这个网址查看:http://sourceforge.net/apps/mediawiki/mjpg-streamer/index.php?title=Main_Page
source code的网址是:http://mjpg-streamer.svn.sourceforge.net/viewvc/mjpg-streamer/
mjpg-stream的移植需要jpeg的库,所以我们先移植jpeg的库
(1)jpeg库的移植
1)jpeg源码包通过下面这个网址下载
http://www.ijg.org/files/jpegsrc.v8b.tar.gz
2)解压源码包
tar xvf jpegsrc.v8b.tar.gz
3)配置源码
cd jpeg-8b
./configure --prefix=/home/fengjunhui/securitymonitor/mjpeg-streamer/video/jpegarm --host=arm-none-linux-gnueabi
(注意:--prefix表示最终生成的库和头文件等存放的目录,自己指定一个存在的路径就可以,
后面编译mjpeg-streamer的时候回用到,此处必须使用绝对路径,--host=arm-none-linux-gnueabi --host表示生成的库的运行平台,注意是两个 - ,末尾不能加- ,./configure 之后为一行命令)
比如我的路径: pwd
/home/fengjunhui/securitymonitor/mjpeg-streamer/video/jpegarm
(这个目录建议自己创建一个在mjpeg-streamer的上一级目录下)
4)编译
make
5)安装
make install
6)拷贝库到文件系统中
sudo cp /home/fengjunhui/securitymonitor/mjpeg streamer/video/jpegarm/lib/* /home/fengjunhui/source/rootfs/lib
(2)、移植mjpg-streamer
1、下载源码,在https://sourceforge.net/projects/mjpg-streamer/下载的源码(mjpg-streamer-code-182) 最新的版本使用以下命令下载,
svn cohttps://mjpg-streamer.svn.sourceforge.NET/svnroot/mjpg-streamermjpg-streamer
解压,并进入目录一共有 这么多目录
doc mjpg-streamer udp_client
mjpeg-client mjpg-streamer-experimental uvc-streamer
mjpg-streamer :目录下提供了 的执行程序和各个输入输出设备组件
uvc-streamer : 目录下提供了 uvc-streamer的可执行目录
mjpeg-client: : 分别有 linux和windows 的客户端
2、进入其目录
cd /home/mjpg/mjpg-streamer-code-182/mjpg-streamer
3、修改源码
修改
vi ./plugins/input_uvc/Makfile,
修改
CFLAGS += -O1 -DLINUX -D_GNU_SOURCE -Wall -shared -fPIC
为
CFLAGS += -O1 -DLINUX -D_GNU_SOURCE -Wall -shared -fPIC -I /home/fengjunhui/securitymonitor/mjpeg-streamer/video/jpegarm/include
修改
(CC)(CFLAGS) -o @inputuvc.cv4l2uvc.lojpegutils.lodynctrl.lo(LFLAGS)
为 (注意还是一行,不要直接复制粘贴,根据实际情况思考来做)
(CC)(CFLAGS) -L /home/fengjunhui/securitymonitor/mjpeg-streamer/video/jpegarm/lib –o @inputuvc.cv4l2uvc.lojpegutils.lodynctrl.lo(LFLAGS)
注:/home/fengjunhui/securitymonitor/mjpeg-streamer/video/jpegarm/lib就是上面移植jpeg库后生成的lib、include的目录的路径,千万不要写错了
4、在mjpg-streamer-code-182/mjpg-streamer 目录下
编译:make CC=arm-linux-gcc
在mjpg-streamer生成了
input*.so output*.so 和 mjpg_streamr 可执行文件
小问题:
make CC=arm-linux-gcc
make: svnversion: Command not found
解决方案:sudo apt-get install subversion
安装之前先更新一下软件包的源和依赖:
Sudo apt-get update 更新软件源
Sudo apt-get -f install 更新依赖
再次编译:
make
Nothing to be done for `all'.
先
make clean,
然后再
make CC=arm-linux-gcc
查看生成的库和可执行的文件:
fengjunhui@ubuntu:~/securitymonitor/mjpeg-streamer/mjpg-streamer-code-182/mjpg-streamer$ ls *.so
input_file.so input_uvc.so output_http.so
input_testpicture.so output_file.so output_udp.so
ls mjpg_streamer
mjpg_streamer
5、在开发板建立mjpg-streamer安装目录 (关键性的拷贝过程)
mkdir /home/fengjunhui/source/rootfs/mjpg-streamer (你的根文件系统目录)
cp *.so /home/fengjunhui/source/rootfs/mjpg-streamer -arf
cp mjpg_streamer /home/fengjunhui/source/rootfs/mjpg-streamer -arf
将源码目录中的start.sh和目录www拷贝到~/source/rootfs/mjpg-streamer/目录下,然后就可以测试啦
sudo cp start.sh www/ ~/source/rootfs/mjpg-streamer/ -arf
- 测试:
./start.sh (记得插上摄像头设备喔)
MJPEG格式错误,
ERROR opening V4L interface: No such file or directory
Init v4L2 failed !! exit fatal
i: init_VideoIn failed
MJPG-streamer [1296]: init_VideoIn failed
解决方案:
- 插上USB摄像头,查看设备节点: ls /dev/video0
- 如果没有设备节点,则参考《ttyUSB0设备节点不显示的解决方案.doc》
视频流格式错误:
cannot be displayed because it contains errors
修改start.sh文件,加参数-y,然后运行start.sh;
./mjpg_streamer -i “./input_uvc.so -y” -o “./output_http.so -w ./www”
在PC机打开一个网页,输入http://192.168.1.100:8080/?action=stream就可以看到图像。 (板子ip)
以上是mjpg-streamer的移植全过程,下面说说在这过程可能出现的错误以及解决方法。
1、当编译mjpg-stream-r63时出错
[root@wu mjpg-stream-r63]# make CC=arm-linux-gcc
arm-linux-gcc -O3 -DLINUX -D_GNU_SOURCE -Wall -c -o mjpg_streamer.o mjpg_streamer.c
mjpg_streamer.c:27:28: fatal error: linux/videodev.h: No such file or directory
compilation terminated.
make: * [mjpg_streamer.o] 错误 1
原因:这是因为内核2.6.38和以后的版本已经移除了对 v4l1 的支持,这个东西可能比较老旧了。新的头文件是 video4linux2.h;相比v4l1很多接口都变化 。
解决办法:可以选择以前低版本内核,或者用新版本的mjpg-streamer-code-182,下载地址在上面有链接。
3、使用摄像头出现如下信息
………………..
Init v4L2 failed !! exit fatal
init_VideoIn failed
………………..
原因:市面上大部分摄像头都是支持YUV的,而不是JPEG的。
解决方法:由于mjpg-stream支持JPEG和YUV两种格式,所以只需修改start.sh,在输入中加入 ” - y “
假如原来是./mjpg_streamer -i “./input_uvc.so ” -o “./output_http.so -w ./www”,则改为
./mjpg_streamer -i “./input_uvc.so -y” -o “./output_http.so -w ./www”即可。
总结:经过一轮的谷歌+百度后终于可以在firefox看了摄像头采集的图像
4、缺少库的支持
root@makeru :/mjpg-streamer# ./start.sh
MJPG-streamer [1308]: starting application
MJPG Streamer Version: svn rev:
MJPG-streamer [1308]: MJPG Streamer Version: svn rev:
ERROR: could not find input plugin
MJPG-streamer [1308]: ERROR: could not find input plugin
Perhaps you want to adjust the search path with:
MJPG-streamer [1308]: Perhaps you want to adjust the search path with:
# export LD_LIBRARY_PATH=/path/to/plugin/folder
MJPG-streamer [1308]: # export LD_LIBRARY_PATH=/path/to/plugin/folder
dlopen: libjpeg.so.8: cannot open shared object file: No such file or directory
MJPG-streamer [1308]: dlopen: libjpeg.so.8: cannot open shared object file: No such file or directory
忘记拷贝库(这里需要保证你拷贝的库是ARM格式的 file libjpeg.so.8 )
cp /home/fengjunhui/securitymonitor/mjpeg-streamer/video/jpegarm/lib/ /home/fengjunhui/source/rootfs/lib
cd mjpg-streamer-code-182/mjpg-streamer
cp *.so /home/fengjunhui/source/rootfs/mjpg-streamer -arf
cp mjpg-stream /home/fengjunhui/source/rootfs/mjpg-streamer -arf
将源码目录中的start.sh和目录www拷贝到~/source/rootfs/mjpg-streamer/目录下,然后就可以测试啦
sudo cp start.sh www/ ~/source/rootfs/mjpg-streamer/ -arf
7、获得帮助
获得帮助的方法在start.sh里有说明,以下举一个例子,运行./mjpg_streamer –help它会打印出以下帮助,可根据需要设置参数
The following parameters can be passed to this plugin:
[-d | –device ]…….: video device to open (your camera)
[-r | –resolution ]…: the resolution of the video device,
can be one of the following strings
QSIF QCIF CGA QVGA CIF VGA
SVGA XGA SXGA
or a custom value like the following
example: 640x480
[-f | –fps ]……….: frames per second
[-y | –yuv ]……….: enable YUYV format and disable MJPEG mode
[-q | –quality ]……: JPEG compression quality in percent
(activates YUYV format, disables MJPEG)
[-m | –minimum_size ].: drop frames smaller then this limit, useful
if the webcam produces small-sized garbage frames
may happen under low light conditions
[-n | –no_dynctrl ]…: do not initalize dynctrls of Linux-UVC driver
[-l | –led ]……….: switch the LED “on”, “off”, let it “blink” or leave
it up to the driver using the value “auto”
最后
本期实验结果我放在了bilibili中,最后别忘了在开发板上启动 boa 和 monitor_obj 程序。
把linux、web和摄像头加起来会怎么样
行业前瞻智慧物联网如何重塑视频监控的未来?
智能手机可以视作是物联网设备的原型。安防摄像头很快将在安防和安保方面发挥类似的作用。在本文中,我们将带大家了解新技术和应用如何改变该行业的游戏规则。让我们看看视频监控是如何发展到今天的,以及它的未来的发展方向。
与其他传感器(例如运动或烟雾探测器)一起使用的安防摄像头已经使用了很长时间,但并未通过数据网络相互连接。公共空间、商业建筑、公共交通等领域对智能视频监控的需求不断增长,以及智慧物联网的兴起,将推动这些摄像头系统的进一步集成。
过去:传统的安防监控系统
闭路电视系统 (CCTV) 已经证明它们可以做他们应该做的事情:让人们更好地了解安防状况,以减少安全事故。闭路电视摄像机只能显示和录制视频片段,仅此而已。由于它们不明白它们在看什么,所以说能力有限。
为了有效打击盗窃、暴力、故意破坏或火灾,安防摄像头必须能够自行检测和识别此类事件。它们还必须具有与其他系统(例如警报系统)联动的能力。
这就是物联网发挥作用的地方。它将支持网络的摄像机与执行其他任务的其他设备和系统连接起来,并将安防监控转变为智能安防与报警管理。
小知识:你可知道?
CCTV 技术于 1942 年首次在德国使用,旨在监控 V-2 导弹。直到 1949 年,该技术才以商业方式引入美国。
视频监控系统在 2018 年成为全球安防市场最大的细分市场。这就是为什么今天安防摄像系统被广泛应用于生活、零售、商业建筑、体育场馆、交通和城市公共场所管理等场景。
安防摄像头构成了安防监控发展的下一个技术趋势。
未来:智慧化的安防监控
视频监控系统只提供必须由人工持续观察的视频时代已经结束。能够一次性记录、检测和分析视频数据的技术已经面世,它们可以为管理人员提供深入的视频数据洞察,而不是单一的信息。
通过对任何类型的事件做出更快、更深入的响应,这将显着改善许多领域和行业的安防相关流程。
未来的安防监控本质上结合了 3 种技术,它们将彻底改变游戏规则:计算机视觉、自动化和深度学习,由强大的处理器和物联网摄像头上的应用驱动。
1)计算机视觉
由于更复杂的算法、更快的设备、更大的网络以及通过物联网访问更广泛的数据集,计算机视觉变得越来越智能。这项技术允许机器实时“查看”和分析视频。计算机视觉中的深度学习和通用人工智能技术使肉眼无法做到的事情成为可能。
示例:在几秒钟内检测到火灾和烟雾
许多安防隐患,例如烟雾,人眼很难在视频中检测到,尤其是在光线不足的情况下。然而,配备烟雾和火灾探测功能的安防摄像头可以在检测到烟火时发出警报,并在没有任何人工协助的情况下启动适当的烟火喷淋等安防措施。
2)自动化
速度在安防工作方面发挥着重要作用。对安全事件的反应越快,预防或至少减少损失的机会就越大。例如在商店发生盗窃的情况下,响应时间就显得非常重要,因为盗窃者可能会在保安人员介入之前消失。
通过闭路电视进行传统的安防监控会浪费宝贵的时间,因为机器和工作人员之间的反应路径太长。智能摄像头则通过节省人工识别视频内容来走捷径。它们会立即发送告警通知或自行启动适当的操作。
示例:在零售业中检测和抓捕小偷
某些安防系统搭载AI智能识别技术,可帮助店主及时识别潜在的小偷。通过摄像头扫描实时视频流并分析它可以看到的任何访客的姿势。此数据会自动与预定义的“可疑”行为进行匹配。当它看到一些异常的东西时,它会通过应用提醒现场工作人员进行双重检查。
3)深度学习
摄像头捕捉视频,但视频分析技术可以获取到更有价值的视频信息。深度学习是一种基于人工神经网络的机器学习方法。视频分析技术使安防摄像头能够分析采集到的视频数据,是深度学习的一种应用。
深度学习的好处在于,用于开发 AI 视频分析应用的开发人员不必自己重新发明轮子。当前已经有复杂的框架可以简化深度学习模型的开发。支持深度学习的计算机视觉系统提供准确的视觉数据分析,可用于在各种环境条件下实现视频监控的自动化。
新兴技术和应用——例如多维感知、UHD(超高清)、微光成像、人工智能和云技术——为安防行业开辟了新的可能性。与此同时,数以百万计的摄像头和其他安全设备正在联网,使安防行业成为未来物联网世界中非常重要的一部分。
人工智能技术正在逐渐成为主流。在接下来的 10 年中,人工智能视频分析技术将成为整个视频监控解决方案的标准要求。 AI 视频分析将成为未来 10 年视频监控业务的第一大改变者,影响构成该业务的大多数产品的增长。
总结
物联网 (IoT) 和相关技术带来的增强功能是推动当前城市发展的重要因素。视频监控是一个在物联网和其他智能技术驱动下经历重大发展的领域。而随着AI、5G、大数据、云计算等新兴技术的发展与应用,视频监控也将迎来更多发展空间。
与此同时,TSINGSEE青犀视频不断拓展视频监控技术在多领域的深耕和发展。一方面,通过AI智能分析实现对视频内容的智能检测与分析,在大数据的支撑上辅助用户进行决策;另一方面,将旗下视频融合云平台、实时流媒体技术、AI+“云-边-端”架构理念,与5G场景融合,并深度应用在城市、安防、交通、教育、旅游、消防、电力、工地、能源与环保等多个行业领域中。
以上是关于实战物联网安防监控项目———把模拟数据传输到web网页web显示mjpeg-streamer视频图像的主要内容,如果未能解决你的问题,请参考以下文章
学员源鑫笔记韦东山物联网流媒体实战项目-智慧家居视频监控系统(值得收藏)...
学员源鑫笔记韦东山物联网流媒体实战项目-智慧家居视频监控系统(值得收藏)...