将SD卡中保存的摄像头(OV7620)数据合成8位灰度图像

暑假的时候做车用到SD卡保存摄像头OV7620的数据,采用SPI,图片大小是155*60,刚开始学这个没加什么东西,直接就把数据往SD里面塞,初始化创建了一个data1.txt的文件

rc =f_open(&testdata,"0:/data1.txt",FA_CREATE_ALWAYS|FA_WRITE);
     if(FR_OK == rc)OLED_P6x8Str(0,4,"f_open is ok");

接下来就直接保存图像数据

      for(i = 0;i < 60;i++)
      {
        for(j = 0;j < 156;j++)
        {
          if(j == 155)
            filebuff[j] = 0;
          else
            filebuff[j]=ImageData[i][j];   
        }
        f_write(&testdata,filebuff,156,&bw);
      }

保存完了数据直接打开不了,后来整了一天怎么把这些数据合成bmp位图,下面是在vc++6.0用c语言写的

/**
文件名:createbmp.c
日期:2016.8.17
版本:2.0
作者:逆风
功能:实现将SD卡中保存的摄像头数据合成8位灰度图像(*.bmp),方便在小豹上位机上分析图像
使用方法:将SD卡中保存数据的txt文件放至指定路径(本程序是:G:\\101.txt)
运行createbmp.exe,如果没有出现错误则将在G盘根目录生成bmp位图(*.bmp)(从0.bmp,1.bmp...n.bmp)
*/
#include <STDIO.H>
#include <STRING.H>
#include <STDLIB.H>

//摄像头采集图像的大小要对应这里bmp位图的大小
#define WIDTH   155 //合成的bmp位图的宽,即摄像头采集的列数
#define HEIGHT  60  //合成的bmp位图的高,即摄像头采集的行数
#define WIDTHbyte 156//这里设置的156是因为必须为4的整数倍,即采集的155列向上补齐为156

#pragma pack(push, 1) 

typedef unsigned char  U8; 
typedef unsigned short U16; 
typedef unsigned int   U32; 

//文件信息头,占14个字节
typedef struct tagBITMAPFILEHEADER  
{  

    U16 bfType; //说明文件的类型,该值必需是0x4D42,也就是字符'BM'
    U32 bfSize; //说明文件的大小,以字节为单位
    U16 bfReserved1; //保留,设置为0 
    U16 bfReserved2; //保留,设置为0
    U32 bfOffBits; //   说明从BITMAPFILEHEADER结构开始到实际图像数据阵列字节间的字节偏移量
    //这个参数是非常有用的,因为位图信息头和调色板的长度会根据不同情况而变化,
    //所以你可以用这个偏移值迅速的从文件中读取到位数据
} BITMAPFILEHEADER; 

//位图信息头,占40个字节
typedef struct tagBITMAPINFOHEADER  
{  
    U32 biSize; //表示BITMAPINFOHEADER结构所需要的字节数
    U32 biWidth; //表示图像的宽度,以像素为单位
    U32 biHeight; 
    /*表示图像的高度,以像素为单位。
    注:这个值除了用于描述图像的高度之外,它还有另一个用处,就是指明该图像是倒向的位图,
    还是正向的位图。如果该值是一个正数,说明图像是倒向的,如果该值是一个负数,则说明图像是正向的。
    大多数的BMP文件都是倒向的位图,也就是时,高度值是一个正数。
    */
    U16 biPlanes; //为目标设备说明位面数,其值将总是被设为1
    U16 biBitCount; //表示比特数/像素,其值为1、4、8、16、24、或32
    U32 biCompression; //表示图像数据压缩的类型,没有压缩的类型:BI_RGB(即为0)
    U32 biSizeImage; //表示图像的大小,以字节为单位。当用BI_RGB格式时,可设置为0
    U32 biXPelsPerMeter; //表示水平分辨率,用像素/米表示
    U32 biYPelsPerMeter; //表示垂直分辨率,用像素/米表示
    U32 biClrUsed; //表示位图实际使用的彩色表中的颜色索引数(设为0的话,则说明使用所有调色板项)
    U32 biClrImportant; //表示对图像显示有重要影响的颜色索引的数目,如果是0,表示都重要
} BITMAPINFOHEADER; 

//颜色表(调色板)(为可选项)
typedef struct tagRGBQUAD 
{  
    U8 rgbBlue; // 蓝色的亮度(值范围为0-255)
    U8 rgbGreen; // 绿色的亮度(值范围为0-255)
    U8 rgbRed;  // 红色的亮度(值范围为0-255)
    U8 rgbReserved; // 保留,必须为0
} RGBQUAD; 

//位图信息头和颜色表组成位图信息
typedef struct tagBITMAPINFO  
{  
    BITMAPINFOHEADER bmiHeader; // 位图信息头
    RGBQUAD bmiColors[1]; // 颜色表
} BITMAPINFO; 

//文件信息头和位图信息组成位图文件
typedef struct tagBITMAP 
{ 
    BITMAPFILEHEADER bfHeader; 
    BITMAPINFO biInfo; 
}BITMAPFILE; 

#pragma pack(pop)

/*
#pragma pack(push, 1) 
...
#pragma pack(pop)
这两句在VC编译时必须加上
如果不加上,由于编译器的问题,这里用BYTE声明,但因为编译器喜欢内存对齐,
实际占了还是4字节,改变一下成1字节对齐声明就可以了
*/

/*
注意:
Windows规定一个扫描行所占的字节数必须是4的倍数(即以long为单位),不足的以0填充。
例如:一张24位10*10的图片,一行图像10个像素,共30字节,
由于Windows规定一个扫描行所占的字节数必须是4的倍数,而不足的以0填充,
所以一行图像在文件中实际存储了32个字节(补了2字节的0);而图片总的大小就不是54+30*10=354字节,
而是54+32*10=374字节
所以:
1. 在生成BMP文件时,如果一行图像的字节数不是4的倍数,则补0,而补后一行图像数据的大小的计算公式为:
bmppitch = ((biWidth * bitCountPerPix + 31) >> 5) << 2;
其中,biWidth--图片的宽度,bitCountPerPix--图片的位数。
2. 在读取BMP文件数据时也要注意这点。
*/

//生成BMP图片    在摄像头传回来数据的基础上加上文件信息头和位图信息头 
int GenBmpFile(U8 (*pData)[WIDTH], U32 width, U32 height, const char *filename) 
{ 
    FILE *fp = fopen(filename, "wb"); 
    if(!fp) 
    { 
        printf("fopen failed : %s, %d/n", __FILE__, __LINE__); 
        return 0; 
    } 
    U32 filesize = WIDTHbyte*height; 

    BITMAPFILE bmpfile; 
    bmpfile.bfHeader.bfType = 0x4D42; 
    bmpfile.bfHeader.bfSize = filesize + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)*256;
    bmpfile.bfHeader.bfReserved1 = 0; 
    bmpfile.bfHeader.bfReserved2 = 0; 
    bmpfile.bfHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)*256; 

    bmpfile.biInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 
    bmpfile.biInfo.bmiHeader.biWidth = width; 
    bmpfile.biInfo.bmiHeader.biHeight = height; 
    bmpfile.biInfo.bmiHeader.biPlanes = 1; 
    bmpfile.biInfo.bmiHeader.biBitCount = 8; //8位bmp图
    bmpfile.biInfo.bmiHeader.biCompression = 0; 
    bmpfile.biInfo.bmiHeader.biSizeImage = 0; 
    bmpfile.biInfo.bmiHeader.biXPelsPerMeter = 0; 
    bmpfile.biInfo.bmiHeader.biYPelsPerMeter = 0; 
    bmpfile.biInfo.bmiHeader.biClrUsed = 0; 
    bmpfile.biInfo.bmiHeader.biClrImportant = 0; 

    //构造灰度图的调色版

    RGBQUAD rgbquad[256];
    int i;
    for(i=0;i<256;i++)
    {
        rgbquad[i].rgbBlue=i;
        rgbquad[i].rgbGreen=i;
        rgbquad[i].rgbRed=i;
        rgbquad[i].rgbReserved=0;
    } 

    fwrite(&(bmpfile.bfHeader), sizeof(BITMAPFILEHEADER), 1, fp); //将文件信息头写进文件
    fwrite(&(bmpfile.biInfo.bmiHeader), sizeof(BITMAPINFOHEADER), 1, fp); //将位图信息头写进文件
    fwrite(&rgbquad,sizeof(RGBQUAD)*256,1, fp); //将调色板写进文件
    //将图像数据写进文件
    U8 *pEachLinBuf = (U8*)malloc(WIDTHbyte); //在内存中开辟空间
    memset(pEachLinBuf, 0, WIDTHbyte); //将pEachLinBuf中所有数据设置为0
    if(pEachLinBuf) 
    { 
        int h,w;
        for(h = height-1; h >= 0; h--) 
        { 
            for(w = 0; w < width; w++) 
            { 
                //copy by a pixel 
                pEachLinBuf[w] = *(*(pData+h)+w); 
            } 
            fwrite(pEachLinBuf, WIDTHbyte, 1, fp);  
        } 
        free(pEachLinBuf); 
    } 
    fclose(fp); 

    return 1; 
} 


int main(char argc, char *argv[]) 
{ 
    U8 pRGB[HEIGHT][WIDTH];  // 定义位图数据  
    memset(pRGB,0,sizeof(pRGB));//将所有数据都设置为0
    long myfilesize = 0;
    FILE *fpread = fopen("F:\\data1.txt", "rb");//打开摄像头保存数据的文件
    if(!fpread) 
    { 
        printf("fopen failed : %s, %d/n", __FILE__, __LINE__); 
        return 0; 
    }
    else
    {
        fseek(fpread,0,SEEK_END);//将文件指针移动文件结尾
        myfilesize = ftell (fpread); ///求出当前文件指针距离文件开始的字节数
        fseek(fpread,0,SEEK_SET);//将文件指针移动文件开头
    }
    char FilePath[1000] = {0};
    int number = 0;
    for(number = 0;number < myfilesize/(HEIGHT*WIDTHbyte);number++)
    {   
        sprintf(FilePath, "F:\\图像%4d.bmp", number);
        int h = 0;
        for(h = 0; h < HEIGHT;h++)
        {
            fread(pRGB[h],WIDTHbyte,1,fpread);//读取每一行的数据。这里设置的156是因为必须为4的整数倍,即采集的155列向上补齐为156
        //  printf("%d\n",fread(pRGB[HEIGHT-1-h],WIDTHbyte,1,fpread));
            if ( ferror ( fpread ) ){//如果读取错误
                printf("File read error.");
            }
        }
        GenBmpFile(&pRGB[0], WIDTH, HEIGHT, FilePath);//生成BMP文件 
    }
    fclose(fpread);
    return 0; 
}

合成的图片:
这里写图片描述
然后就可以用上位机分析图片了
这里写图片描述
暂时还没发现什么大问题,之后有空再优化一下,接下来要是能做出个上位机来直接合成分析就好了

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值