在qt上OpenCV处理OV9650采集的图像

来源:互联网 发布:韩国女团身材管理知乎 编辑:程序博客网 时间:2024/05/13 17:16

网上移植Opencv到ARM+linux上的教程很多,叫我们如何把OV9650采集的数据传递给opencv使用的教程也很多,但是说的模棱两可,没有一个确切的说法。我在这里总结一下。

   一般我们OV9650采集的数据得先经过OpenCV处理以后才会给qt显示,所以要转换两次:第一次是OV9650采集的数据要放到IplImage结构里面,这样Opencv才能使用,第二次是经OpenCV处理以后的图像要传给qt显示。

   、先说第一次转换。OV9650可以采集的数据类型是RGB565、RAW RGB、YUV,这三种数据格式各有特点,RGB565是每个像素16位,即两个字节,数据是交叉排列:[R0,G0,B0]  [ R1,G1,B1]....    RAW RGB是摄像头采集到的数据还没有进行排列,每个像素都有三种颜色,每一个的值在0~255之间,之后我们要进行插值,我们可以插成RGB24,也可以插成BGR24,YUV格式比较流行,但是在我们这里不大适合,因为IlpImage结构中的数据数组一定是深度为8位RGB格式的数据结构,即我们转换的目标是RGB24。

     先熟悉IplImage结构:

 

typedef struct _IplImage
{
int nSize;         /* IplImage大小 */
int ID;            /* 版本 (=0)*/
int nChannels;     /* 大多数OPENCV函数支持1,2,3 或 4 个通道 */
int alphaChannel; /* 被OpenCV忽略 */
int depth;         /* 像素的位深度,主要有以下支持格式: IPL_DEPTH_8U, IPL_DEPTH_8S, IPL_DEPTH_16U,IPL_DEPTH_16S, IPL_DEPTH_32S,
IPL_DEPTH_32F 和IPL_DEPTH_64F */
char colorModel[4]; /* 被OpenCV忽略 */
char channelSeq[4]; /* 同上 */
int dataOrder;     /* 0 - 交叉存取颜色通道, 1 - 分开的颜色通道.
只有cvCreateImage可以创建交叉存取图像 */
int origin;        /*图像原点位置: 0表示顶-左结构,1表示底-左结构 */
int align;         /* 图像行排列方式 (4 or 8),在 OpenCV 被忽略,使用 widthStep 代替 */
int width;        /* 图像宽像素数 */
int height;        /* 图像高像素数*/
struct _IplROI *roi; /* 图像感兴趣区域,当该值非空时,
只对该区域进行处理 */
struct _IplImage *maskROI; /* 在 OpenCV中必须为NULL */
void *imageId;     /* 同上*/
struct _IplTileInfo *tileInfo; /*同上*/
int imageSize;     /* 图像数据大小(在交叉存取格式下ImageSize=image->height*image->widthStep),单位字节*/
char *imageData;    /* 指向排列的图像数据 */
int widthStep;     /* 排列的图像行大小,以字节为单位 */
int BorderMode[4]; /* 边际结束模式, 在 OpenCV 被忽略*/
int BorderConst[4]; /* 同上 */
char *imageDataOrigin; /* 指针指向一个不同的图像数据结构(不是必须排列的),是为了纠正图像内存分配准备的 */
} IplImage;

    所以我们只需要创建一个深度为8,通道数为3的IplImage结构:

      IplImage* image = cvCreateImage(cvSize(WIDTH*HEIHT), 8, 3),然后再把IplImage结构的数据数组指针*imageData给下面的转换函数,把转换成的RGB24数据放到imageData数组里就行了。

 

    1、RGB565转IlpImage

         思路:先把RGB565中的每个分量放到一个字节里面,这样就转成了RGB24见下图:

  

那么RGB565一个像素位2字节,RGB24一个像素3个字节,也就是24位,一下代码是网上摘来:

方式一:

[cpp] view plaincopy
  1. #define RGB565_MASK_RED 0xF800   
  2. #define RGB565_MASK_GREEN 0x07E0   
  3. #define RGB565_MASK_BLUE 0x001F   
  4.   
  5. unsigned short *pRGB16 = (unsigned short *)lParam;  // lParam为OV9650采集数据的缓冲数组,数组类型一定要是unsigned short,也就是16位  
[cpp] view plaincopy
  1. //转换以后的数组放在一个char数组里面,数组大小是高乘以宽的三倍  
[cpp] view plaincopy
  1. for(int i=0; i<176*144; i++)   
  2. {   
  3.     unsigned short RGB16 = *pRGB16;   
  4.     g_rgbbuf[i*3+2] = (RGB16&RGB565_MASK_RED) >> 11;     
  5.     g_rgbbuf[i*3+1] = (RGB16&RGB565_MASK_GREEN) >> 5;   
  6.     g_rgbbuf[i*3+0] = (RGB16&RGB565_MASK_BLUE);   
  7.     g_rgbbuf[i*3+2] <<= 3;   
  8.     g_rgbbuf[i*3+1] <<= 2;   
  9.     g_rgbbuf[i*3+0] <<= 3;   
  10.     pRGB16++;   
  11. }   
[cpp] view plaincopy
  1. <br style="TEXT-ALIGN: left; WIDOWS: 2; TEXT-TRANSFORM: none; BACKGROUND-COLOR: rgb(255,255,255); TEXT-INDENT: 0px; FONT: 12px/26px 宋体, Arial; WORD-WRAP: break-word; WHITE-SPACE: normal; ORPHANS: 2; LETTER-SPACING: normal; COLOR: rgb(102,102,102); WORD-SPACING: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><span style="color:#666666;TEXT-ALIGN: left; WIDOWS: 2; TEXT-TRANSFORM: none; BACKGROUND-COLOR: rgb(255,255,255); TEXT-INDENT: 0px; DISPLAY: inline !important; FONT: 12px/26px 宋体, Arial; WHITE-SPACE: normal; ORPHANS: 2; FLOAT: none; LETTER-SPACING: normal; WORD-SPACING: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">方式二:</span><br style="TEXT-ALIGN: left; WIDOWS: 2; TEXT-TRANSFORM: none; BACKGROUND-COLOR: rgb(255,255,255); TEXT-INDENT: 0px; FONT: 12px/26px 宋体, Arial; WORD-WRAP: break-word; WHITE-SPACE: normal; ORPHANS: 2; LETTER-SPACING: normal; COLOR: rgb(102,102,102); WORD-SPACING: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">  
[cpp] view plaincopy
  1. rgb5652rgb888(unsigned char *image,unsigned char *image888)   
  2. {   
  3. unsigned char R,G,B;   
  4. B=(*image) & 0x1F;//000BBBBB   
  5. G=( *(image+1) << 3 ) & 0x38 + ( *image >> 5 ) & 0x07 ;//得到00GGGGGG00   
  6. R=( *(image+1) >> 3 ) & 0x1F; //得到000RRRRR   
  7. *(image888+0)=B * 255 / 63; // 把5bits映射到8bits去,自己可以优化一下算法,下同   
  8. *(image888+1)=G * 255 / 127;   
  9. *(image888+2)=R * 255 / 63;   
  10. }   

     下面是我根据第一种修改的代码:

  

[cpp] view plaincopy
  1. <span style="font-size:18px;"> IplImage* temp = cvCreateImage(cvSize(WIDTH*HEIHT), 8, 3);  //创建结构体  
  2.  int ret=-1;      
  3.          
  4.  if ((ret=read(fd,&buf,size_2)) != size_2)   //read 1 fram  
  5.           //读取一帧  
  6.   
  7.         {  
  8.         perror("read");  
  9.         return -1;  
  10.      }  
  11.   
  12.       
  13. for(int i=0; i<size_1; i++)   //convert RGB565 to RGB24  
  14.       
  15.          {   
  16.       
  17.         *(temp->imageData+i*3+2) = (buf[i]&RGB565_MASK_RED) >> 11;     
  18.         *(temp->imageData+i*3+1) = (buf[i]&RGB565_MASK_GREEN) >> 5;   
  19.         *(temp->imageData+i*3+0) = (buf[i]&RGB565_MASK_BLUE);   
  20.         *(temp->imageData+i*3+2) <<= 3;   
  21.         *(temp->imageData+i*3+1) <<= 2;   
  22.         *(temp->imageData+i*3+0) <<= 3;   
  23.   
  24.       }   
  25.   
  26.   
  27. </span>  



 2、RGB565转成bmp图像保存下来,使用OpenCV函数加载

[cpp] view plaincopy
  1. /**********************RBG565 TO BMP*************************************/  
  2. struct tagBITMAPFILEHEADER{  
  3.   
  4.    unsigned long bfSize;  
  5.    unsigned long bfLeft;  
  6.    unsigned long bfOffBits;  
  7.   
  8. };  
  9.   
  10. struct tagBITMAPINFOHEADER{  
  11.    unsigned long biSize;  
  12.    unsigned long bmpWidth;  
  13.    unsigned long bmpHeight;  
  14.    unsigned short biPlanes;  
  15.    unsigned short bicolors;  
  16.    unsigned long isCompressed;  
  17.    unsigned long biMapSize;  
  18.    unsigned long biHorizontal;  
  19.    unsigned long biVertical;  
  20.    unsigned long biusedcolors;  
  21.    unsigned long biimportcolors;   
  22. };  
  23.   
  24. int writebmp(unsigned short *bmp,int height,int width,char *filepath)  
  25. {  
  26.    int i,j,size;  
  27.    int fd;  
  28.    struct tagBITMAPFILEHEADER bfhead;  
  29.    struct tagBITMAPINFOHEADER binfohead;  
  30.    size=height*width;  
  31.   
  32.    bfhead.bfSize=0x36+size*2;  
  33.    bfhead.bfLeft=0;  
  34.    bfhead.bfOffBits=0x36;  
  35.   
  36.    binfohead.biSize=0x28;  
  37.    binfohead.bmpWidth=width;  
  38.    binfohead.bmpHeight=height;  
  39.    binfohead.biPlanes=1;  
  40.    binfohead.bicolors=0x10;  
  41.    binfohead.isCompressed=0;  
  42.    binfohead.biMapSize=size*2;  
  43.    binfohead.biHorizontal=0x0b13;  
  44.    binfohead.biVertical=0x0b13;  
  45.    binfohead.biusedcolors=0;  
  46.    binfohead.biimportcolors=0;  
  47.      
  48.   
  49.    if(access(filepath,F_OK)!=0)  //For the first time  
  50.    {  
  51.            fd=open(filepath,O_CREAT |O_RDWR);  
  52.            write(fd,"BM",2);  
  53.        i=write(fd,&bfhead,sizeof(struct tagBITMAPFILEHEADER)); //Write filehead  
  54.        i=write(fd,&binfohead,sizeof(struct tagBITMAPINFOHEADER)); //Write infohead   
  55.        i=write(fd,bmp,size*2); //Write bitmap  
  56. //     lseek(fd,SEEK_SET,4); //move th point  
  57.    }  
  58.    else  
  59.    {  
  60.            fd=open(filepath,O_RDWR);  
  61.            int headsize=sizeof(struct tagBITMAPFILEHEADER)+sizeof(struct tagBITMAPINFOHEADER);  
  62.            lseek(fd,headsize,SEEK_SET);  
  63.            write(fd,bmp,size*2); //Write bitmap  
  64.       
  65.    }  
  66.   
  67.        return 1;  
  68. }  
  69.   
  70.   
  71. int grab(unsigned short *buff1)  
  72. {  
  73. unsigned short bmp[WIDTH*HEIGHT];  
  74. int i,j;  
  75. /*RBG565_TO_RGB555*/  
  76. for(i=0;i<HEIGHT;i++)  
  77.     for(j=0;j<WIDTH;j++)  
  78.        {  
  79.   
  80.        *(bmp+i*WIDTH+j)=((*(buff1+i*WIDTH+j)&0xf800)>>1)|((*(buff1+i*WIDTH+j)&0x07c0)>>1)|(*(buff1+i*WIDTH+j)&0x1f);  
  81.          
  82.        //printf("%x\t",*(bmp+i*WIDTH+j));  
  83.        }  
  84.   
  85. i=HEIGHT,j=WIDTH;  
  86. writebmp(bmp, i, j,"/process");   //抓图保存在为/process.bmp  
  87.   
  88. }  
  89.   
  90. /***********************************************************/  


 

3、RAW RGB排列成RGB24

      网上有教程。

4、YUV转成JPEG图片,使用OpenCV函数加载。下面给出转换代码

源文件

[cpp] view plaincopy
  1. #include "yuyv_covert_jpeg.h"  
  2.   
  3. typedef mjpg_destination_mgr *mjpg_dest_ptr;  
  4. struct buffer *         buffers         = NULL;  
  5. FILE *file_fd;  
  6.   
  7.   
  8. METHODDEF(void) init_destination(j_compress_ptr cinfo)  
  9. {  
  10.   
  11.         mjpg_dest_ptr dest = (mjpg_dest_ptr) cinfo->dest;  
  12.         dest->buffer = (JOCTET *)(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, OUTPUT_BUF_SIZE * sizeof(JOCTET));  
  13.         *(dest->written) = 0;  
  14.         dest->pub.next_output_byte = dest->buffer;  
  15.         dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;  
  16.   
  17. }  
  18.   
  19. METHODDEF(boolean) empty_output_buffer(j_compress_ptr cinfo)  
  20. {  
  21.         mjpg_dest_ptr dest = (mjpg_dest_ptr) cinfo->dest;  
  22.         memcpy(dest->outbuffer_cursor, dest->buffer, OUTPUT_BUF_SIZE);  
  23.         dest->outbuffer_cursor += OUTPUT_BUF_SIZE;  
  24.         *(dest->written) += OUTPUT_BUF_SIZE;  
  25.         dest->pub.next_output_byte = dest->buffer;  
  26.         dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;  
  27.   
  28.         return TRUE;  
  29.   
  30. }  
  31.   
  32. METHODDEF(void) term_destination(j_compress_ptr cinfo)  
  33. {  
  34.         mjpg_dest_ptr dest = (mjpg_dest_ptr) cinfo->dest;  
  35.         size_t datacount = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer;  
  36.   
  37.         /* Write any data remaining in the buffer */  
  38.         memcpy(dest->outbuffer_cursor, dest->buffer, datacount);  
  39.         dest->outbuffer_cursor += datacount;  
  40.         *(dest->written) += datacount;  
  41.   
  42. }  
  43.   
  44.   
  45.   
  46. void dest_buffer(j_compress_ptr cinfo, unsigned char *buffer, int size, int *written)  
  47. {  
  48.         mjpg_dest_ptr dest;  
  49.         if (cinfo->dest == NULL) {  
  50.                 cinfo->dest = (struct jpeg_destination_mgr *)(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, sizeof(mjpg_destination_mgr));  
  51.   
  52.         }  
  53.   
  54.         dest = (mjpg_dest_ptr)cinfo->dest;  
  55.         dest->pub.init_destination = init_destination;  
  56.         dest->pub.empty_output_buffer = empty_output_buffer;  
  57.         dest->pub.term_destination = term_destination;  
  58.         dest->outbuffer = buffer;  
  59.         dest->outbuffer_size = size;  
  60.         dest->outbuffer_cursor = buffer;  
  61.         dest->written = written;  
  62.   
  63. }  
  64.   
  65.   
  66. //摄像头采集的YUYV格式转换为JPEG格式  
  67. int compress_yuyv_to_jpeg(unsigned char *buf, unsigned char *buffer, int size, int quality)  
  68. {  
  69.         struct jpeg_compress_struct cinfo;  
  70.         struct jpeg_error_mgr jerr;  
  71.         JSAMPROW row_pointer[1];  
  72.   
  73.         unsigned char *line_buffer, *yuyv;  
  74.         int z;  
  75.         static int written;  
  76.   
  77.         line_buffer = (unsigned char*)calloc (WIDTH * 3, 1);  
  78.         yuyv = buf;//将YUYV格式的图片数据赋给YUYV指针  
  79.         //printf("compress start...\n");  
  80.         cinfo.err = jpeg_std_error (&jerr);  
  81.         jpeg_create_compress (&cinfo);  
  82.   
  83.         /* jpeg_stdio_dest (&cinfo, file); */  
  84.         dest_buffer(&cinfo, buffer, size, &written);  
  85.   
  86.         cinfo.image_width = WIDTH;  
  87.         cinfo.image_height = HEIGHT;  
  88.         cinfo.input_components = 3;  
  89.         cinfo.in_color_space = JCS_RGB;  
  90.   
  91.         jpeg_set_defaults (&cinfo);  
  92.         jpeg_set_quality (&cinfo, quality, TRUE);  
  93.         jpeg_start_compress (&cinfo, TRUE);  
  94.   
  95.         z = 0;  
  96.         while (cinfo.next_scanline < HEIGHT) {  
  97.                 int x;  
  98.                 unsigned char *ptr = line_buffer;  
  99.   
  100.                 for (x = 0; x < WIDTH; x++) {  
  101.                         int r, g, b;  
  102.                         int y, u, v;  
  103.   
  104.                         if (!z)  
  105.                                 y = yuyv[0] << 8;  
  106.                         else  
  107.                                 y = yuyv[2] << 8;  
  108.   
  109.                         u = yuyv[1] - 128;  
  110.                         v = yuyv[3] - 128;  
  111.   
  112.                         r = (y + (359 * v)) >> 8;  
  113.                         g = (y - (88 * u) - (183 * v)) >> 8;  
  114.                         b = (y + (454 * u)) >> 8;  
  115.   
  116.                         *(ptr++) = (r > 255) ? 255 : ((r < 0) ? 0 : r);  
  117.                         *(ptr++) = (g > 255) ? 255 : ((g < 0) ? 0 : g);  
  118.                         *(ptr++) = (b > 255) ? 255 : ((b < 0) ? 0 : b);  
  119.   
  120.                         if (z++) {  
  121.                                 z = 0;  
  122.                                 yuyv += 4;  
  123.                         }  
  124.   
  125.                 }  
  126.   
  127.                 row_pointer[0] = line_buffer;  
  128.                 jpeg_write_scanlines (&cinfo, row_pointer, 1);  
  129.   
  130.         }  
  131.   
  132.         jpeg_finish_compress (&cinfo);  
  133.         jpeg_destroy_compress (&cinfo);  
  134.   
  135.         free (line_buffer);  
  136.   
  137.         return (written);  
  138.   
  139. }  


头文件

 

[cpp] view plaincopy
  1. #ifndef __YVYV2JPEG__  
  2. #define __YVYV2JPEG__  
  3. extern "C" {  
  4. #include <stdio.h>  
  5. #include <stdlib.h>  
  6. #include <string.h>  
  7. #include <assert.h>  
  8. #include <getopt.h>  
  9. #include <fcntl.h>  
  10. #include <unistd.h>  
  11. #include <errno.h>  
  12. #include <malloc.h>  
  13. #include <sys/stat.h>  
  14. #include <sys/types.h>  
  15. #include <sys/time.h>  
  16. #include <sys/mman.h>  
  17. #include <sys/ioctl.h>  
  18. #include <asm/types.h>  
  19. #include <linux/videodev2.h>  
  20. #include <jpeglib.h>  
  21.   
  22.   
  23. #define OUTPUT_BUF_SIZE  4096  
  24. #define WIDTH 320  
  25. #define HEIGHT 240  
  26.   
  27. struct buffer {  
  28.         void   *start;  
  29.         size_t length;  
  30. };  
  31.   
  32. typedef struct {  
  33.         struct jpeg_destination_mgr pub;  
  34.         JOCTET * buffer;  
  35.         unsigned char *outbuffer;  
  36.         int outbuffer_size;  
  37.         unsigned char *outbuffer_cursor;  
  38.         int *written;  
  39.   
  40. } mjpg_destination_mgr;  
  41.   
  42. METHODDEF(void) init_destination(j_compress_ptr cinfo);  
  43. METHODDEF(boolean) empty_output_buffer(j_compress_ptr cinfo);  
  44. METHODDEF(void) term_destination(j_compress_ptr cinfo);  
  45. void dest_buffer(j_compress_ptr cinfo, unsigned char *buffer, int size, int *written);  
  46.   
  47.   
  48. //摄像头采集的YUYV格式转换为JPEG格式  
  49. int compress_yuyv_to_jpeg(unsigned char *buf, unsigned char *buffer, int size, int quality);  
  50.   
  51. }  
  52. #endif   
0 0
原创粉丝点击