在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

Linux開發_攝像頭編程(實現拍照功能)

DS小龍哥-嵌入式技術 ? 2022-09-17 15:34 ? 次閱讀

這篇文章主要介紹Linux下UVC免驅攝像頭操作流程,介紹V4L2框架、完成攝像頭拍照保存為BMP圖像到本地,最后貼出了利用CJSON庫解析天氣預報、北京時間接口返回的數據例子代碼(上篇文章的案例補充)。

任務1:攝像頭操作方式

(1)攝像頭框架介紹

Linux、windows這些系統下很多攝像頭都是免驅(UVC)。

v4l2 :免驅攝像頭框架----一堆結構體。

Linux下開發攝像頭的不同角度問題:(嵌入式開發)

【1】上層軟件系統開發(系統編程),控制驅動提供的接口使用攝像頭。

【2】底層硬件系統開發(驅動編程),直接控制攝像頭采集數據。

攝像頭功能:將采集到的圖像數據轉為二進制數據返回。

驅動的代碼集成在操作系統里。

在操作系統里使用攝像頭步驟:學習接口函數的調用。

fread(); read();

Linux下是一切設備皆文件: 攝像頭、網卡、聲卡、鼠標、鍵盤………………….

Linux下設備文件存放的位置: /dev目錄下。

在虛擬機跑Linux,使用外設設備都需要單獨掛載才可以使用。

掛載攝像頭:

img

查看攝像頭的設備節點:

[root@wbyq /]# ls /dev/video*

/dev/video0 /dev/video1

(2)運行網頁監控項目代碼

遠程網頁視頻監控示例

第一步:編譯libjpeg-turbo
?
1. 解壓:libjpeg-turbo-1.2.1.tar.gz
?
2. 生成Makefile(如果報錯,就安裝報錯提示安裝包):./configure
?
3. 編譯安裝:make && make install
?
4. 將生成lib和include目錄下的文件拷貝到/usr目錄下的對應文件夾
?
第二步:編譯mjpg-streamer-r63
?
1.直接make進行編譯
?
2.運行程序:./mjpg_streamer -i "/work/mjpeg/mjpg-streamer-r63/input_uvc.so -f 10 -r 800*480 -y" -o "/work/mjpeg/mjpg-streamer-r63/output_http.so -w www"
?
注意: 可以使用電腦自帶的攝像頭。在虛擬機的右下角進行將windows系統的攝像頭掛載到Linux系統
?
3. 在瀏覽器里輸入地址進行查看攝像頭:
?
例如:192.168.11.123:8080
復制代碼

將遠程攝像頭監控的代碼編譯運行實現效果。

(1) 修改端口號,8080不能作為公網的端口訪問。

(2) 修改線程數量。

(3) 分析下線程的函數實現原理。

(4) 使用花生殼軟件實現公網監控。

花生殼: 將本地IP地址映射為一個域名。

外網想要訪問本地電腦IP就直接訪問域名。

(3)攝像頭編程,實現拍照功能

學習攝像頭的使用

(1)攝像頭實現拍照源程序流程:(50%程序學過的)

(2)打開攝像頭的設備文件 open(“/dev/xxx”);

(3)獲取攝像頭參數。判斷攝像頭是否支持一些特有的操作。read

(4)配置攝像頭的參數。(1) 輸出的源數據格式RGB888 (2) 輸出的圖像尺寸

RGB888:數字數據格式

其他格式: YUV 模擬數據格式

(5)判斷攝像頭的參數是否設置成功。

(6)讀取攝像頭的數據。 隊列的形式。

(7)將讀取的YUV格式數據轉為RGB格式

(8)將RGB格式數據編碼為BMP格式的圖片存放到電腦上

安裝rpm軟件包:rpm -ivh xxxxx.rpm

Linux下安裝軟件有兩種方式:

【1】rpm軟件安裝包(已經編譯好的二進制文件的集合),使用rpm -ivh xxx.rpm

【2】直接下載源碼包自己編譯安裝。libjpeg-turbo-1.2.1.tar.gz

(1) 沒有makefile文件,就有: configure文件,用來生成makefile文件

示例: ./configure

(2) make 編譯源碼

(3) make install 安裝源碼。(會將編譯好的文件拷貝到指定的目錄下)

img
void *memset(void *s, int c, size_t count) //給指定地址的空間填入指定大小的數據
參數:
*s :起始地址
c :填入的數據
count :填入的數量
RGB888 : 000 FFF
復制代碼

攝像頭拍照示例代碼:

#include "camera_bmp.h"
?
T_PixelDatas Pixedata; //存放實際的圖像數據
?
/*
        USB攝像頭相關參數定義
*/
struct v4l2_buffer tV4l2Buf;
int iFd;
int ListNum;
unsigned char* pucVideBuf[4]; // 視頻BUFF空間地址
?
int main(int argc ,char *argv[])
{
    if(argc!=2)
    {
         printf("./app /dev/videoX\n");
         return -1;
    }
    
    camera_init(argv[1]); //攝像頭設備初始化
?
    //開始采集攝像頭數據,并編碼保存為BMP圖片
    camera_pthread();
    return 0;
}
?
?
//YUV轉RGB實現
unsigned int Pyuv422torgb32(unsigned char * ptr,unsigned int width, unsigned int height)
{
    unsigned int i, size;
    unsigned char Y, Y1, U, V;
    unsigned char *buff = ptr;     //源數據
    unsigned char *output_pt=Pixedata.VideoBuf; //存放轉換之后的數據
    unsigned char r, g, b;
    size = width * height /2;
    for (i = size; i > 0; i--) 
    {
        Y = buff[0];
        U = buff[1];
        Y1= buff[2];
        V = buff[3];
        buff += 4;
        r = R_FROMYV(Y,V);
        g = G_FROMYUV(Y,U,V); //b
        b = B_FROMYU(Y,U); //v
        *output_pt++ = b;
        *output_pt++ = g;
        *output_pt++ = r;
        r = R_FROMYV(Y1,V);
        g = G_FROMYUV(Y1,U,V); //b
        b = B_FROMYU(Y1,U); //v
        *output_pt++ = b;
        *output_pt++ = g;
        *output_pt++ = r;
    }
    return 0;
} 
?
//攝像頭設備的初始化
int camera_init(char *video)
{
    int i=0;
    int cnt=0;
    //定義攝像頭驅動的BUF的功能捕獲視頻
    int iType = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    
    /* 1、打開視頻設備 */
    iFd = open(video,O_RDWR);
    if(iFd < 0)
?    {
?        printf("攝像頭設備打開失敗!\n");
?        return 0;
?    }
?    
?    struct v4l2_format ?tV4l2Fmt;
?    
?    /* 2、 VIDIOC_S_FMT 設置攝像頭使用哪種格式 */
?    memset(&tV4l2Fmt, 0, sizeof(struct v4l2_format));
?    tV4l2Fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; //視頻捕獲
??
?    //設置攝像頭輸出的圖像格式
? ? ?tV4l2Fmt.fmt.pix.pixelformat=V4L2_PIX_FMT_YUYV;
??
?    /*設置輸出的尺寸*/
?    tV4l2Fmt.fmt.pix.width ? ? ? = 640;
?    tV4l2Fmt.fmt.pix.height ? ? ?= 480;
?    tV4l2Fmt.fmt.pix.field ? ? ? = V4L2_FIELD_ANY;
?    
? ? ?//VIDIOC_S_FMT 設置攝像頭的輸出參數
? ? ?ioctl(iFd, VIDIOC_S_FMT, &tV4l2Fmt); 
??
?    //打印攝像頭實際的輸出參數
?    printf("Support Format:%d\n",tV4l2Fmt.fmt.pix.pixelformat);
?    printf("Support width:%d\n",tV4l2Fmt.fmt.pix.width);
?    printf("Support height:%d\n",tV4l2Fmt.fmt.pix.height);
??
?    /* 初始化Pixedata結構體,為轉化做準備 */
?    Pixedata.iBpp =24;                              
?    //高度 和寬度的賦值
?    Pixedata.iHeight = tV4l2Fmt.fmt.pix.height;
?    Pixedata.iWidth = tV4l2Fmt.fmt.pix.width;
??
?    //一行所需要的字節數
?    Pixedata.iLineBytes = Pixedata.iWidth*Pixedata.iBpp/8;
?    //一幀圖像的字節數
?    Pixedata.iTotalBytes = Pixedata.iLineBytes * Pixedata.iHeight;
?    Pixedata.VideoBuf=malloc(Pixedata.iTotalBytes); //申請存放圖片數據空間
??
?    //v412請求命令
?    struct v4l2_requestbuffers tV4l2ReqBuffs;
?    
?    /* 3、VIDIOC_REQBUFS  申請buffer */
?    memset(&tV4l2ReqBuffs, 0, sizeof(struct v4l2_requestbuffers));
??
?    /* 分配4個buffer:實際上由VIDIOC_REQBUFS獲取到的信息來決定 */
?    tV4l2ReqBuffs.count ? = 4;
?    
?    /*支持視頻捕獲功能*/
?    tV4l2ReqBuffs.type ? ?= V4L2_BUF_TYPE_VIDEO_CAPTURE;
?    
?    /* 表示申請的緩沖是支持MMAP */
?    tV4l2ReqBuffs.memory ?= V4L2_MEMORY_MMAP;
?    
?    /* 為分配buffer做準備 */
?    ioctl(iFd, VIDIOC_REQBUFS, &tV4l2ReqBuffs);
?    
?    for (i = 0; i < tV4l2ReqBuffs.count; i++) 
?    {
?        memset(&tV4l2Buf, 0, sizeof(struct v4l2_buffer));
?        tV4l2Buf.index = i;
?        tV4l2Buf.type ? = V4L2_BUF_TYPE_VIDEO_CAPTURE;
?        tV4l2Buf.memory = V4L2_MEMORY_MMAP;
??
?        /* 6、VIDIOC_QUERYBUF 確定每一個buffer的信息 并且 mmap */
?        ioctl(iFd, VIDIOC_QUERYBUF, &tV4l2Buf);
?        //映射空間地址
?        pucVideBuf[i] = mmap(0 /* start anywhere */ ,
?                 ?tV4l2Buf.length, PROT_READ, MAP_SHARED, iFd,
?                 ?tV4l2Buf.m.offset);
?        printf("mmap %d addr:%p\n",i,pucVideBuf[i]);
?    }
??
?    /* 4、VIDIOC_QBUF  放入隊列*/
? ? ?for (i = 0; i 在LCD上顯示:rgb888 */
?    initLut();
?    printf("開始采集數據.......\n");
?    FD_ZERO(&readfds);
?    FD_SET(iFd,&readfds);
?    select(iFd+1,&readfds,NULL,NULL,NULL);
? ?
?    memset(&tV4l2Buf, 0, sizeof(struct v4l2_buffer));
?    tV4l2Buf.type ? ?= V4L2_BUF_TYPE_VIDEO_CAPTURE; //類型
?    tV4l2Buf.memory ?= V4L2_MEMORY_MMAP; //存儲空間類型
??
?    /* 9、VIDIOC_DQBUF ?  從隊列中取出 */
?    error = ioctl(iFd, VIDIOC_DQBUF, &tV4l2Buf); //取出一幀數據
?    ListNum = tV4l2Buf.index; //索引編號
?    
?    //將YUV轉換為RGB
?    Pyuv422torgb32(pucVideBuf[ListNum],Pixedata.iWidth,Pixedata.iHeight);
?    
?    //保存BMP
?    save_bmp(Pixedata.VideoBuf); 
?    memset(&tV4l2Buf, 0, sizeof(struct v4l2_buffer));
?    tV4l2Buf.index ?= ListNum;
?    tV4l2Buf.type ? = V4L2_BUF_TYPE_VIDEO_CAPTURE;
?    tV4l2Buf.memory = V4L2_MEMORY_MMAP;
?    error = ioctl(iFd, VIDIOC_QBUF, &tV4l2Buf);
?}
??
??
?/*-----------------保存為BMP格式的圖片------------------*/
?typedef unsigned char ?BYTE;
?typedef unsigned short  WORD;
?typedef unsigned long ?DWORD;
??
?#pragma pack(1)
?typedef struct tagBITMAPFILEHEADER{
? ? ? WORD    ?bfType; ? ? ? ? ? ? ? ?// the flag of bmp, value is "BM"
? ? ? DWORD ? ?bfSize; ? ? ? ? ? ? ? ?// size BMP file ,unit is bytes
? ? ? DWORD ? ?bfReserved; ? ? ? ? ? ?// 0
? ? ? DWORD ? ?bfOffBits; ? ? ? ? ? ? // must be 54  RGB數據存放位置
?}BITMAPFILEHEADER;
??
?typedef struct tagBITMAPINFOHEADER{
? ? ? DWORD ? ?biSize; ? ? ? ? ? ?// must be 0x28
? ? ? DWORD ? ?biWidth; ? ? ? ? ? // 寬度
? ? ? DWORD ? ?biHeight; ? ? ? ? ?// 高度
? ? ? WORD ? ? biPlanes; ? ? ? ? ?// must be 1
? ? ? WORD    ?biBitCount; ? ? ? ? ? ?// 像素位數
? ? ? DWORD ? ?biCompression; ? ? ? ? //
? ? ? DWORD ? ?biSizeImage; ? ? ? //
? ? ? DWORD ? ?biXPelsPerMeter; ? //
? ? ? DWORD ? ?biYPelsPerMeter; ? //
? ? ? DWORD ? ?biClrUsed; ? ? ? ? ? ? //
? ? ? DWORD ? ?biClrImportant; ? ? ? ?//
?}BITMAPINFOHEADER;
??
??
?//保存為BMP格式的文件
?void save_bmp(char *src)
?{
?    /*-----------------------------------------------------------
?                    獲取時間參數,用來給圖片命名
?    -------------------------------------------------------------*/
?    time_t t;
? ? ?struct tm *tmp;
? ? ?char buffer[1024] = {0};
? ? ?t = time(NULL);
? ? ?tmp=localtime(&t);
? ? ?if(strftime(buffer, sizeof(buffer), "%Y%m%d%H%M%S_", tmp) == 0) 
? ?  {
? ?      printf("timer error\n");
? ?  }
?    
?    static int cnt=0; ? ? ?//靜態變量存放總數量
?    cnt++;
?    if(cnt>=20)cnt=0;   //清理計數器
    char str[10];
    sprintf(str,"%d",cnt); //整數轉為字符串
    
    strcat(buffer,str);
    strcat(buffer,".bmp");
    printf("%s\n",buffer); //打印圖片的名稱
    
    /*-----------------------------------------------------------
                        獲取圖片數據,用來保存為BMP圖片格式
    -------------------------------------------------------------*/
  FILE * fp;
  int i;
  BITMAPFILEHEADER  bf;
  BITMAPINFOHEADER  bi;
  
  memset(&bf ,0 ,sizeof(BITMAPFILEHEADER));
  memset(&bi ,0 ,sizeof(BITMAPINFOHEADER));
?
  fp = fopen(buffer, "wb");
  if(!fp)
   {
        printf("open %s error\n",buffer);
        return ;
    }
?
    //Set BITMAPINFOHEADER 設置BMP信息頭
    bi.biSize = sizeof(BITMAPINFOHEADER);//40;
    bi.biWidth = Pixedata.iWidth;//IMAGEWIDTH;
    bi.biHeight = Pixedata.iHeight;//IMAGEHEIGHT;
    bi.biPlanes = 1;
    bi.biBitCount = 24;//8;
    bi.biCompression = 0;
    bi.biSizeImage =Pixedata.iHeight*Pixedata.iWidth*3; //;0
    bi.biXPelsPerMeter = 0;
    bi.biYPelsPerMeter = 0;
    bi.biClrUsed = 0;// 1<<(bi.biBitCount)
?    bi.biClrImportant = 0;
??
? ? ?//Set BITMAPFILEHEADER
? ? ?bf.bfType = 0x4d42; //'B''M'
? ? ?bf.bfSize = 54 + bi.biSizeImage;// sizeof(BITMAPFILEHEADER); ? ?
? ? ?bf.bfReserved = 0;
? ? ?bf.bfOffBits = 54;
? ? ? ? 
? ? ?fwrite(&bf, sizeof(BITMAPFILEHEADER), 1, fp);
? ? ?fwrite(&bi, sizeof(BITMAPINFOHEADER), 1, fp); ? ?
? ? ?fwrite(src, Pixedata.iWidth*Pixedata.iHeight*3,1,fp);
? ? ?fclose(fp);
?}
??
?/*----------------------YUV轉RGB算法-------------------*/
??
?static int *LutYr = NULL;
?static int *LutYg = NULL;;
?static int *LutYb = NULL;;
?static int *LutVr = NULL;;
?static int *LutVrY = NULL;;
?static int *LutUb = NULL;;
?static int *LutUbY = NULL;;
?static int *LutRv = NULL;
?static int *LutGu = NULL;
?static int *LutGv = NULL;
?static int *LutBu = NULL;
??
??
?unsigned char RGB24_TO_Y(unsigned char r, unsigned char g, unsigned char b)
?{
?    return (LutYr[(r)] + LutYg[(g)] + LutYb[(b)]);
?}
??
?unsigned char YR_TO_V(unsigned char r, unsigned char y)
?{
?    return (LutVr[(r)] + LutVrY[(y)]);
?}
??
?unsigned char YB_TO_U(unsigned char b, unsigned char y)
?{
?    return (LutUb[(b)] + LutUbY[(y)]);
?}
??
?unsigned char R_FROMYV(unsigned char y, unsigned char v)
?{
?    return CLIP((y) + LutRv[(v)]);
?}
??
?unsigned char G_FROMYUV(unsigned char y, unsigned char u, unsigned char v)
?{
?    return CLIP((y) + LutGu[(u)] + LutGv[(v)]);
?}
??
?unsigned char B_FROMYU(unsigned char y, unsigned char u)
?{
?    return CLIP((y) + LutBu[(u)]);
?}
??
?void initLut(void)
?{
?    int i;
?    #define Rcoef 299 
?    #define Gcoef 587 
?    #define Bcoef 114 
?    #define Vrcoef 711 //656 //877 
?    #define Ubcoef 560 //500 //493 564
?    
?    #define CoefRv 1402
?    #define CoefGu 714 // 344
?    #define CoefGv 344 // 714
?    #define CoefBu 1772
?    
?    LutYr = malloc(256*sizeof(int));
?    LutYg = malloc(256*sizeof(int));
?    LutYb = malloc(256*sizeof(int));
?    LutVr = malloc(256*sizeof(int));
?    LutVrY = malloc(256*sizeof(int));
?    LutUb = malloc(256*sizeof(int));
?    LutUbY = malloc(256*sizeof(int));
?    
?    LutRv = malloc(256*sizeof(int));
?    LutGu = malloc(256*sizeof(int));
?    LutGv = malloc(256*sizeof(int));
?    LutBu = malloc(256*sizeof(int));
?    for (i= 0;i < 256;i++)
?    {
?     ? ?LutYr[i] = i*Rcoef/1000 ;
?     ? ?LutYg[i] = i*Gcoef/1000 ;
?     ? ?LutYb[i] = i*Bcoef/1000 ;
?     ? ?LutVr[i] = i*Vrcoef/1000;
?     ? ?LutUb[i] = i*Ubcoef/1000;
?     ? ?LutVrY[i] = 128 -(i*Vrcoef/1000);
?     ? ?LutUbY[i] = 128 -(i*Ubcoef/1000);
?     ? ?LutRv[i] = (i-128)*CoefRv/1000;
?     ? ?LutBu[i] = (i-128)*CoefBu/1000;
?     ? ?LutGu[i] = (128-i)*CoefGu/1000;
?     ? ?LutGv[i] = (128-i)*CoefGv/1000;
?    }   
?}
??
??
?void freeLut(void)
?{
?    free(LutYr);
?    free(LutYg);
?    free(LutYb);
?    free(LutVr);
?    free(LutVrY);
?    free(LutUb);
?    free(LutUbY);
?    
?    free(LutRv);
?    free(LutGu);
?    free(LutGv);
?    free(LutBu);
?}
復制代碼;>

(4)解析北京時間

#include 
#include 
#include 
#include "cJSON.h"
#include 
#include 
#include 
?
/*
標準時間運行格式: ./app
*/
int GetData(char *src);
int main(int argc,char **argv)
{   
    /*1. 拼接訪問的鏈接路徑*/
    char src[200];
    char str[]="http://api.k780.com:88/?app=life.time'&'appkey=10003'&'sign=b59bc3ef6191eb9f747dd4e83c99f2a4'&'format=json >data.txt";
    
    strcpy(src,"curl ");
    strcat(src,str);
    system(src); //執行瀏覽器數據
    
    /*2. 讀取源數據*/
    FILE *file=fopen("data.txt","rb");
    if(file==NULL)
    {
        printf("文件打開失敗!\n");
        exit(-1);
    }
    
    struct stat file_stat_buf;
    stat("data.txt",&file_stat_buf); //獲取文件的狀態
    
    char *src_data=malloc(file_stat_buf.st_size);
    if(src_data==NULL)
    {
        printf("%s文件第%d行,出現錯誤:空間失敗!\n",__FILE__,__LINE__);
        exit(-1);
    }
    
    fread(src_data,1,file_stat_buf.st_size,file); //讀取源數據到緩沖區
    
    /*3. 數據解析*/
    GetData(src_data);
    
    /*4. 釋放空間*/
    free(src_data);
    return 0;
}
?
/*
函數功能:獲取具體的數據
函數形參:保存json的源數據首地址
*/
int GetData(char *src)
{
    /*1. 載入源數據,獲取根對象*/
    cJSON *root=cJSON_Parse(src);
    if(root==NULL)
    {
        printf("%s文件第%d行,出現錯誤:獲取根對象失敗!\n",__FILE__,__LINE__);
        return -1;
    }
    
    /*2. 獲取對象中的值*/
    cJSON *json=cJSON_GetObjectItem(root,"success");
    if(json==NULL)
    {
        printf("%s文件第%d行,出現錯誤:獲取json對象失敗!\n",__FILE__,__LINE__);
        return -1;
    }
    
    //判斷獲取的值是否成功
    if(strcmp(json->valuestring,"1")!=0)
    {
        printf("%s文件第%d行,出現錯誤:時間獲取失敗!\n",__FILE__,__LINE__);
        return -1;
    }
    
    
    //獲取結果
    json=cJSON_GetObjectItem(root,"result");
    if(json==NULL)
    {
        printf("%s文件第%d行,出現錯誤:獲取json對象失敗!\n",__FILE__,__LINE__);
        return -1;
    }
    
    //獲取秒單位時間
    cJSON *data=cJSON_GetObjectItem(json,"timestamp");
    if(data==NULL)
    {
        printf("%s文件第%d行,出現錯誤:獲取json對象失敗!\n",__FILE__,__LINE__);
        return -1;
    }
    printf("秒單位的時間:%s\n",data->valuestring);
    
    data=cJSON_GetObjectItem(json,"datetime_1");
    if(data==NULL)
    {
        printf("%s文件第%d行,出現錯誤:獲取json對象失敗!\n",__FILE__,__LINE__);
        return -1;
    }
    printf("datetime_1:%s\n",data->valuestring);
    
    data=cJSON_GetObjectItem(json,"datetime_2");
    if(data==NULL)
    {
        printf("%s文件第%d行,出現錯誤:獲取json對象失敗!\n",__FILE__,__LINE__);
        return -1;
    }
    printf("datetime_2:%s\n",data->valuestring);
    
    
    data=cJSON_GetObjectItem(json,"week_1");
    if(data==NULL)
    {
        printf("%s文件第%d行,出現錯誤:獲取json對象失敗!\n",__FILE__,__LINE__);
        return -1;
    }
    printf("week_1:%s\n",data->valuestring);
    
    
    data=cJSON_GetObjectItem(json,"week_2");
    if(data==NULL)
    {
        printf("%s文件第%d行,出現錯誤:獲取json對象失敗!\n",__FILE__,__LINE__);
        return -1;
    }
    printf("week_2:%s\n",data->valuestring);
    
    data=cJSON_GetObjectItem(json,"week_3");
    if(data==NULL)
    {
        printf("%s文件第%d行,出現錯誤:獲取json對象失敗!\n",__FILE__,__LINE__);
        return -1;
    }
    printf("week_3:%s\n",data->valuestring);
    
    data=cJSON_GetObjectItem(json,"week_4");
    if(data==NULL)
    {
        printf("%s文件第%d行,出現錯誤:獲取json對象失敗!\n",__FILE__,__LINE__);
        return -1;
    }
    printf("week_4:%s\n",data->valuestring);
    /* */
    cJSON_Delete(root);
}
復制代碼

(5)解析天氣預報

#include 
#include 
#include 
#include "cJSON.h"
#include 
#include 
#include 
?
/*
標準時間運行格式: ./app
*/
int GetData(char *src);
int main(int argc,char **argv)
{   
    if(argc!=2)
    {
        printf("參數格式: ./app <城市名稱>\n");
        return 0;
    }
    /*1. 拼接訪問的鏈接路徑*/
    char src[200];
    char str1[]="http://api.k780.com:88/?app=weather.future'&'weaid=";
    char str2[]="'&&'appkey=10003'&'sign=b59bc3ef6191eb9f747dd4e83c99f2a4'&'format=json >data.txt";
    
    strcpy(src,"curl ");
    strcat(src,str1);
    strcat(src,argv[1]);
    strcat(src,str2);
    
    system(src); //執行瀏覽器數據
    
    /*2. 讀取源數據*/
    FILE *file=fopen("data.txt","rb");
    if(file==NULL)
    {
        printf("文件打開失敗!\n");
        exit(-1);
    }
    
    struct stat file_stat_buf;
    stat("data.txt",&file_stat_buf); //獲取文件的狀態
    
    char *src_data=malloc(file_stat_buf.st_size);
    if(src_data==NULL)
    {
        printf("%s文件第%d行,出現錯誤:空間失敗!\n",__FILE__,__LINE__);
        exit(-1);
    }
    
    fread(src_data,1,file_stat_buf.st_size,file); //讀取源數據到緩沖區
    
    /*3. 數據解析*/
    GetData(src_data);
    
    /*4. 釋放空間*/
    free(src_data);
    return 0;
}
?
/*
函數功能:獲取具體的數據
函數形參:保存json的源數據首地址
*/
int GetData(char *src)
{
    /*1. 載入源數據,獲取根對象*/
    cJSON *root=cJSON_Parse(src);
    if(root==NULL)
    {
        printf("%s文件第%d行,出現錯誤:獲取根對象失敗!\n",__FILE__,__LINE__);
        return -1;
    }
    
    /*2. 獲取對象中的值*/
    cJSON *json=cJSON_GetObjectItem(root,"success");
    if(json==NULL)
    {
        printf("%s文件第%d行,出現錯誤:獲取json對象失敗!\n",__FILE__,__LINE__);
        return -1;
    }
    
    //判斷獲取的值是否成功
    if(strcmp(json->valuestring,"1")!=0)
    {
        printf("%s文件第%d行,出現錯誤:時間獲取失敗!\n",__FILE__,__LINE__);
        return -1;
    }
    
    
    //獲取結果
    json=cJSON_GetObjectItem(root,"result");
    if(json==NULL)
    {
        printf("%s文件第%d行,出現錯誤:獲取json對象失敗!\n",__FILE__,__LINE__);
        return -1;
    }
?
    //獲取數組大小
    int cnt=cJSON_GetArraySize(json); 
    printf("cnt=%d\n",cnt);
    int i;
    for(i=0;ivaluestring);
        
        p=cJSON_GetObjectItem(data,"days");
        printf("days=%s\n",p->valuestring);
        
        p=cJSON_GetObjectItem(data,"week");
        printf("week=%s\n",p->valuestring);
        
        p=cJSON_GetObjectItem(data,"cityno");
        printf("cityno=%s\n",p->valuestring);
        
        p=cJSON_GetObjectItem(data,"citynm");
        printf("citynm=%s\n",p->valuestring);
        
        p=cJSON_GetObjectItem(data,"cityid");
        printf("cityid=%s\n",p->valuestring);
        
        p=cJSON_GetObjectItem(data,"temperature");
        printf("temperature=%s\n",p->valuestring);
        
        p=cJSON_GetObjectItem(data,"humidity");
        printf("humidity=%s\n",p->valuestring);
        
        p=cJSON_GetObjectItem(data,"weather");
        printf("weather=%s\n",p->valuestring);
        
        p=cJSON_GetObjectItem(data,"wind");
        printf("wind=%s\n",p->valuestring);
        
        p=cJSON_GetObjectItem(data,"winp");
        printf("winp=%s\n",p->valuestring);
        
        p=cJSON_GetObjectItem(data,"winp");
        printf("winp=%s\n",p->valuestring);
        printf("\n\n");
    }
    cJSON_Delete(root);
}

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • Linux
    +關注

    關注

    87

    文章

    11304

    瀏覽量

    209483
  • 攝像頭
    +關注

    關注

    60

    文章

    4841

    瀏覽量

    95691
  • 編程
    +關注

    關注

    88

    文章

    3615

    瀏覽量

    93732
收藏 人收藏

    評論

    相關推薦

    安防監控攝像頭氣密性測試案例-連拓精密#攝像頭氣密檢測設備

    攝像頭
    連拓精密科技
    發布于 :2024年12月11日 15:00:21

    攝像頭及紅外成像的基本工作原理

    本文介紹了攝像頭及紅外成像的基本工作原理,攝像頭可以將看到的圖像真實的呈現出來,所見即所得! 攝像頭如何工作? 攝像頭可以將看到的圖像真實的呈現出來,所見即所得。 ? 比如人眼看到的一
    的頭像 發表于 11-25 09:28 ?379次閱讀
    <b class='flag-5'>攝像頭</b>及紅外成像的基本工作原理

    用于環視和CMS攝像頭系統的四通道攝像頭應用程序

    電子發燒友網站提供《用于環視和CMS攝像頭系統的四通道攝像頭應用程序.pdf》資料免費下載
    發表于 10-11 10:02 ?0次下載
    用于環視和CMS<b class='flag-5'>攝像頭</b>系統的四通道<b class='flag-5'>攝像頭</b>應用程序

    【飛凌嵌入式OK3576-C開發板體驗】 USB攝像頭拍照測試

    USB攝像頭拍照 將 USB 攝像頭插入開發板,將自動安裝 uvc 驅動 使用命令查看usb攝像頭,已經將USB
    發表于 10-10 09:24

    基于FPGA的攝像頭心率檢測裝置設計

    的 OpenCV 等開源庫,可以使眾多圖像處理步驟得到簡化,有利于實現更復雜的功能。 2.4 各模塊介紹2.4.1.數據采集模塊 使用攝像頭拍攝人臉畫面,通過 usb 接口與 fpga
    發表于 07-01 17:58

    esp32-s2-soala-v1.2如何獲取攝像頭描述符?

    開發板:esp32-s2-soala-v1.2 開發環境:WIN10 + IDF4.4 我想使用uvc攝像頭的例程,啥都沒改測試初始化是成功的,但是獲取圖片后就會卡死 應該是攝像頭沒有
    發表于 06-27 06:48

    替換SiTime,汽車攝像頭可使用國產可編程振蕩

    替換SiTime,汽車攝像頭可使用國產可編程振蕩
    的頭像 發表于 06-18 09:34 ?276次閱讀
    替換SiTime,汽車<b class='flag-5'>攝像頭</b>可使用國產可<b class='flag-5'>編程</b>振蕩

    智能攝像頭抄表器是什么?

    進行圖像識別,實現無接觸、無誤差的遠程抄表,極大地提高了抄表效率和準確性。2.技術原理與優勢2.1AI圖像識別:智能攝像頭抄表器的核心在于其內置的AI算法,能夠準
    的頭像 發表于 04-24 14:14 ?623次閱讀
    智能<b class='flag-5'>攝像頭</b>抄表器是什么?

    全志D1-H開發板USB攝像頭拍照Demo

    USB攝像頭拍照Demo 本章節將講解如何D1-H上使用一個USB攝像頭拍攝一張照片。 D1-H哪吒開發板上有一個USB Host接口(即電腦上那種插鼠標鍵盤的USB口),同時D1-H
    發表于 03-04 10:48

    爆蘋果正在探索開發攝像頭的AirPods

    據知名蘋果爆料記者馬克?古爾曼消息,蘋果正在探索開發攝像頭的AirPods。
    的頭像 發表于 02-27 15:04 ?839次閱讀

    高清網絡攝像頭多媒體智能屏

    。同時,在屏幕上顯示攝像頭畫面可直接通過DGUS開發實現,十分快捷。硬件接口展示:產品特點支持通過以太網、WiFi(2.4GHz、5GHz均可)連接網絡攝像頭;支
    的頭像 發表于 02-19 13:21 ?588次閱讀
    高清網絡<b class='flag-5'>攝像頭</b>多媒體智能屏

    如何使用ESP32攝像頭模塊構建簡單的CCTV安全攝像頭

    我們將向您展示如何使用 ESP32 攝像頭模塊構建自己的簡單 CCTV安全攝像頭。從修改硬件連接到編碼功能和啟用遠程訪問,加入我們的分步教程,打造經濟高效且可定制的監控解決方案。
    的頭像 發表于 02-11 11:54 ?7253次閱讀
    如何使用ESP32<b class='flag-5'>攝像頭</b>模塊構建簡單的CCTV安全<b class='flag-5'>攝像頭</b>

    用usb攝像頭替換手機前置攝像頭可以嗎

    將從技術實現、可行性和使用體驗三方面,探討這個問題。 一、技術實現: USB攝像頭的連接:USB攝像頭通過USB接口與智能手機連接。目前,大部分智能手機都支持USB On-The-Go
    的頭像 發表于 01-08 14:11 ?2777次閱讀

    AHD攝像頭與CVBS的區別

    (Composite Video Baseband Signal,復合視頻基帶信號)攝像頭,具有許多顯著的優勢。本文章將詳細介紹AHD攝像頭與CVBS攝像頭的區別。 圖像質量 AHD攝像頭
    的頭像 發表于 01-04 11:08 ?1.5w次閱讀
    主站蜘蛛池模板: 第四色播日韩第一页| 一级片+国产| 特黄特黄| 一区二区三区网站| 91美女啪啪| 亚洲欧美视频在线观看| 四虎在线精品| 欧美综合成人网| 黑人边吃奶边扎下面激情视频| 高清国产一区二区三区| 亚洲天天综合| 久操视频在线观看免费| 久久婷婷婷| 两人性世界| 亚洲国产系列| 123456成年免费视频| 色色色色色色色色色色色色 | 天天噜噜日日噜噜久久综合网| 老司机午夜网站| 久久99热精品免费观看k影院| 伊人久久大香线蕉影院95| 色老头在线精品视频在线播放| 成人国内精品久久久久影院| 亚洲人成影院在线高清| 美女扒开尿口给男人爽的视频 | 亚洲国产色图| 欧美zooz人禽交免费| 国产高清视频在线免费观看| 天天看天天做| www.三级| 欧美一级片在线视频| 涩涩涩综合在线亚洲第一| 黄色在线播放网址| 日本特黄a级高清免费大片18| 国产美女视频免费| 欧美中出| 欧美精品一区视频| 国产精品天天影视久久综合网| 网站免费黄| 天天干天天舔| 亚洲国产精品综合久久网络|