Chinaunix首页 | 论坛 | 博客
  • 博客访问: 5399595
  • 博文数量: 1271
  • 博客积分: 12961
  • 博客等级: 上将
  • 技术积分: 15141
  • 用 户 组: 普通用户
  • 注册时间: 2009-01-09 11:25
个人简介

偷得浮生半桶水(半日闲), 好记性不如抄下来(烂笔头). 信息爆炸的时代, 学习是一项持续的工作.

文章分类

全部博文(1271)

文章存档

2020年(55)

2019年(193)

2018年(81)

2017年(80)

2016年(70)

2015年(52)

2014年(41)

2013年(51)

2012年(85)

2011年(45)

2010年(231)

2009年(287)

分类: 其他平台

2018-04-19 15:54:21

g++ main.cpp `pkg-config --libs opencv`

点击(此处)折叠或打开

  1. #include <unistd.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <stdio.h>
  5. #include <sys/types.h>
  6. #include <sys/stat.h>
  7. #include <fcntl.h>


  8. //摄像头通用接口
  9. #include <opencv2/opencv.hpp>
  10. #include <opencv2/highgui/highgui.hpp>
  11. #include <opencv2/imgproc/imgproc.hpp>
  12. #include <opencv2/core/core.hpp>
  13. #include <opencv2/objdetect/objdetect.hpp>
  14. #include <signal.h>
  15. #include <sys/socket.h>
  16. #include <arpa/inet.h>
  17. #include <netinet/in.h>
  18. using namespace cv;
  19. /* Video 通用接口 */
  20. typedef struct {
  21.     int             idx;
  22.     VideoCapture     *stream;
  23.     Mat                frame;
  24. }WebcamContext;
  25. static WebcamContext gCtx[3] = {0}; //目前最大支持 3 个摄像头.

  26. //打开摄像头
  27. static int InitCameraViaID(int idx, int camera_idx, int w, int h)
  28. {
  29.     //参数检查
  30.     gCtx[idx].stream = new VideoCapture(camera_idx);
  31.     if (!gCtx[idx].stream) {
  32.         printf("Cannot open Camera %d\n", camera_idx);
  33.         exit(-1);
  34.         return -1;
  35.     }
  36.     gCtx[idx].stream->set(CV_CAP_PROP_FRAME_WIDTH, w);
  37.     gCtx[idx].stream->set(CV_CAP_PROP_FRAME_HEIGHT, h);
  38.     return 0;
  39. }

  40. static void FinalCamera(void)
  41. {
  42.     for (int i=0; i<sizeof(gCtx)/sizeof(gCtx[0]); i++) {
  43.         if (gCtx[i].stream) {
  44.             gCtx[i].stream->release();
  45.             gCtx[i].stream = NULL;
  46.             if (!gCtx[i].frame.empty())
  47.                 gCtx[i].frame.release();
  48.         }
  49.     }
  50. }

  51. //获取摄像头的数据
  52. static Mat Get_Picture(int idx)
  53. {
  54.     gCtx[idx].stream->read(gCtx[idx].frame);
  55.     return gCtx[idx].frame;
  56. }

  57. static void save_bmp_to_file(int idx, uint8_t* bmp, int bmp_size)
  58. {    
  59.     char filename[128];
  60.     sprintf(filename, "/tmp/jpg/%d.bmp", idx);
  61.     int fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0666);
  62.     if (fd > 0) {
  63.         write(fd, bmp, bmp_size);
  64.         close(fd);
  65.     }    
  66. }

  67. #define dbg()        printf("%d.\n", __LINE__)
  68. static uint8_t* convert_Mat_to_BMP(Mat *img, int *bmp_size);

  69. int main(int argc, char **argv)
  70. {
  71.     int idx = 0;
  72.     
  73.     InitCameraViaID(0, 1, 800, 600);
  74.     
  75.     int bmp_size, fd;
  76.     uint8_t* bmp = NULL;
  77.     
  78.     while (idx++ < 10) {
  79.         Mat frame = Get_Picture(0);                
  80.         bmp = convert_Mat_to_BMP(&frame, &bmp_size);
  81.         save_bmp_to_file(idx, bmp, bmp_size);
  82.         
  83.         usleep(1000000);    
  84.     }
  85.     
  86.     FinalCamera();
  87.     return 0;
  88. }

  89. //convert Mat-object to bmp-struct.

  90. //https://www.cnblogs.com/lzlsky/archive/2012/08/16/2641698.html
  91. typedef uint32_t            DWORD;
  92. typedef uint16_t            WORD;
  93. typedef int32_t                LONG;
  94. typedef uint8_t                BYTE;

  95. typedef struct tagBITMAPFILEHEADER {
  96.     WORD    bfType;                 //2
  97.     DWORD    bfSize;                 //6
  98.     WORD    bfReserved1;             //8
  99.     WORD    bfReserved2;             //10
  100.     DWORD    bfOffBits;                 //14
  101. } __attribute__((packed)) BITMAPFILEHEADER;

  102. typedef struct tagBITMAPINFOHEADER{
  103.     DWORD        biSize;             //4
  104.     LONG        biWidth;             //8
  105.     LONG        biHeight;             //12
  106.     WORD        biPlanes;             //14
  107.     WORD        biBitCount;         //16
  108.     DWORD        biCompression;         //20
  109.     DWORD        biSizeImage;         //24
  110.     LONG        biXPelsPerMeter;     //28
  111.     LONG        biYPelsPerMeter;     //32
  112.     DWORD        biClrUsed;             //36
  113.     DWORD        biClrImportant;     //40
  114. } __attribute__((packed)) BITMAPINFOHEADER;


  115. typedef struct tagRGBQUAD {
  116.     BYTE rgbBlue;
  117.     BYTE rgbGreen;
  118.     BYTE rgbRed;
  119.     BYTE rgbReserved;
  120. } __attribute__((packed)) RGBQUAD;

  121. //return the pointer of BMP-in-memeory.
  122. /*
  123. input: Mat -> img
  124. output: bmp_size
  125. return: bmp_buffer pointer. (need to free by USER)
  126. */
  127. static uint8_t *convert_Mat_to_BMP(Mat *img, int *bmp_size)
  128. {
  129.     uint8_t *pBmpArray = NULL;
  130.     //======建立位图信息 ===========
  131.     int width, height, depth, channel;
  132.     width = img->cols;
  133.     height = img->rows;
  134.     depth = img->depth();
  135.     channel = img->channels();
  136.     
  137.     printf("w=%d h=%d d=%d c=%d\n", width, height, depth, channel);
  138.     
  139.     int bits, colors;
  140.     uint8_t idx;
  141.     bits = (8 << (depth/2)) * channel;
  142.     
  143. #if 0    
  144.     if (bits > 8)
  145.         colors = 0;
  146.     else
  147.         colors = 1<<bits; //now, bits must be 8; so color = 256
  148. #endif
  149.         
  150.     if (bits == 24)
  151.         bits = 32;
  152.         
  153.     //待存储图像数据每行字节数为4的倍数
  154.     int lineByte=(width * bits/8+3)/4*4;
  155.     
  156.     int colorTablesize = 0;
  157.     if (bits == 8) { // 256 色位图, // 设置灰阶调色板
  158.         colorTablesize = 256 * sizeof(RGBQUAD);
  159.     }    
  160. ///////////////////////////////////////////////////////////////////////////////////////////////////////////    
  161.     DWORD    bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + colorTablesize + lineByte*height;
  162.     //bitmap 文件 buffer
  163.     pBmpArray = (uint8_t *)malloc(bfSize);
  164.     memset(pBmpArray, 0, bfSize);
  165.     *bmp_size = bfSize;
  166. ///////////////////////////////////////////////////////////////////////////////////////////////////////////    
  167.     BITMAPFILEHEADER *fileHead = (BITMAPFILEHEADER *)pBmpArray; // sizeof(BITMAPFILEHEADER) = 14;
  168.     fileHead->bfType = 0x4D42;    //bmp类型
  169.     //bfSize是图像文件4个组成部分之和
  170.     fileHead->bfSize = bfSize;
  171.     //bfOffBits是图像文件前3个部分所需空间之和
  172.     fileHead->bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + colorTablesize;
  173. ///////////////////////////////////////////////////////////////////////////////////////////////////////////    
  174.     //位图的头
  175.     BITMAPINFOHEADER *head = (BITMAPINFOHEADER *)(&pBmpArray[sizeof(BITMAPFILEHEADER)]); // sizeof(BITMAPINFOHEADER) = 40;
  176.     head->biSize            = 40;
  177.     head->biWidth            = width;
  178.     head->biHeight            = height;
  179.     head->biPlanes            = 1;
  180.     head->biBitCount        = bits; //表示颜色用到的位数
  181.     head->biCompression        = 0; //0:不压缩(用BI_RGB表示)
  182.     head->biSizeImage        = lineByte*height; //图像数据站的字节数
  183.     head->biXPelsPerMeter    = 0;
  184.     head->biYPelsPerMeter    = 0;
  185.     head->biClrUsed            = 0;
  186.     head->biClrImportant    = 0;
  187. ///////////////////////////////////////////////////////////////////////////////////////////////////////////    
  188.     RGBQUAD *VgaColorTab = (RGBQUAD *)(&pBmpArray[sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)]);
  189.     if (bits == 8) { // 256 色位图, // 设置灰阶调色板
  190.         for (idx=0;idx<256;idx++) {
  191.             VgaColorTab[idx].rgbRed=VgaColorTab[idx].rgbGreen=VgaColorTab[idx].rgbBlue= idx;
  192.         }
  193.     }
  194. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  195.     //======颠倒数据
  196.     //======Mat 中从上往下存,而 bitmap 中从下往上存。 都是从左往右,并 且 bitmap 每一个点多占一个保留字节,默认 255
  197.     unsigned char *m_pDibBits = pBmpArray + fileHead->bfOffBits ;//存储图像中的数据,从下向上,从左向右 //x行 * Y列
  198.     int x, y;
  199.     unsigned char * bmpdata;
  200.     unsigned char * imgData = img->data;
  201.     
  202.     if (bits == 8)
  203.     {
  204.         //把 imgData 中的第一行复制到 m_pDibBits 的最后一行 , 依次颠倒
  205.         for (x=0; x<height; x++ )
  206.         {
  207.             bmpdata = m_pDibBits + (height-1-x)*width;
  208.             memcpy(bmpdata,imgData,width);
  209.             imgData = imgData + width;
  210.         }
  211.     }
  212.     else if (bits == 32)
  213.     {
  214.         //把 imgData 中的第一行复制到 m_pDibBits 的最后一行 , 依次颠倒
  215.         for (x=0; x<height; x++ )
  216.         {
  217.             bmpdata = m_pDibBits + (height-1-x)*width*4;
  218.             for (y = 0; y<width; y++)
  219.             {
  220.                 memcpy(bmpdata,imgData,3);
  221.                 bmpdata[3] = 255;
  222.                 bmpdata = bmpdata+4;
  223.                 imgData = imgData+3;
  224.             }
  225.         }
  226.     }
  227.     
  228. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  229.     return pBmpArray;
  230. }

阅读(10606) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~