FC2カウンター FPGAの部屋 ZYBOのUbuntu上でカメラ画像をBMPファイルに変換できた
FC2ブログ

FPGAやCPLDの話題やFPGA用のツールの話題などです。 マニアックです。 日記も書きます。

FPGAの部屋

FPGAの部屋の有用と思われるコンテンツのまとめサイトを作りました。Xilinx ISEの初心者の方には、FPGAリテラシーおよびチュートリアルのページをお勧めいたします。

ZYBOのUbuntu上でカメラ画像をBMPファイルに変換できた

カメラ画像をUIO領域にDMAし、それをキャプチャ画像として停止することができたので、カメラ画像をBMPファイルに変換することにした。

まずは、カメラの画像をBMPファイルに変換するソフトウエア disp2bmp.c を作った。bmpheader.h も必要だった。BMPヘッダの定義は、”BMP ファイルフォーマット”さんから引用させて頂いた。
./disp2bmp でカメラ画像をBMPファイルにしてから、ZYBOのUbuntu 上で gimp を起動してJPGファイルに変換した。
ZYBO_Cam_Linux_73_141125.png

変換した default.jpg ファイルだ。
default_141125.jpg

これで、カメラ画像からJPGファイルすることができたので、OpenCVの顔認証アプリケーションを使用して、カメラ画像で顔認証を確かめてみることができそうだ。

disp2bmp.c と bmpheader.h を貼っておく。
disp2bmp.c から下に示す。(2014/11/29:修正 詳しい経緯は、”ZYBO用カメラ画像をOpenCVで顔認証した”を参照して下さい。)

//
// disp2bmp.c
//
// Created on: 2014/11/24
//     Author: Masaaki
// カメラの画像をBMPファイルに変換する
//

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <sys/mman.h>
#include <fcntl.h>

#include "bmpheader.h"

#define HORIZONTAL_PIXEL    800
#define VERTICAL_LINES      600

#define CMA_START_ADDRESS 0x17800000
#define VIDEO_BUFFER_START_ADDRESS  0x18000000  // Limit 0x18800000, 800*600*4 = 2MBytes * 2

int main(int argc, char * argv[])
{
    char bmp_file[300];
    BITMAPFILEHEADER bmpfh; // BMPファイルのファイルヘッダ
    BITMAPINFOHEADER bmpih; // BMPファイルのINFOヘッダ
    BMP24FORMAT **bmp_data; // 24ビットのBMPファイルのデータ HORIZONTAL_PIXEL * VERTICAL_LINES
    FILE *fbmp;
    int i, j;
    int fd3;
    volatile unsigned int *frame_buffer, *fb_base_addr;

    // 引数の処理
    if (argc == 1) { // 引数なし
        strcpy(bmp_file, "default.bmp");
    } else if (argc == 2){ // 
        strcpy(bmp_file, (const char *)argv[1]);
    } else {
        fprintf(stderr, "disp2bmp <BMP file name>\n");
        exit(1);
    }

    // メモリをアロケートする
    if ((bmp_data=(BMP24FORMAT **)malloc(sizeof(BMP24FORMAT *)*VERTICAL_LINES)) == NULL){
        fprintf(stderr, "bmp_dataの1次元目の VERTICAL_LINES のメモリを確保できません\n");
        exit(1);
    }
    for (i=0; i<VERTICAL_LINES; i++){
        if ((bmp_data[i]=(BMP24FORMAT *)malloc(sizeof(BMP24FORMAT) * HORIZONTAL_PIXEL)) == NULL){
            fprintf(stderr, "bmp_dataの2次元目の%d番目のメモリが確保できません\n", i);
            exit(1);
        }
    }

    // Frame Buffer UIO3
    fd3 = open("/dev/uio3", O_RDWR); // Frame Buffer
    if (fd3 < 1){
        fprintf(stderr, "/dev/uio3 open error\n");
        exit(-1);
    }
    frame_buffer = (volatile unsigned int *)mmap(NULL, 0x1000000, PROT_READ|PROT_WRITE, MAP_SHARED, fd3, 0);
    if (!frame_buffer){
        fprintf(stderr, "frame_buffer mmap error\n");
        exit(-1);
    }

    // キャプチャ画像のベースアドレスを設定する
    fb_base_addr = (volatile unsigned int *)((unsigned int)frame_buffer + (VIDEO_BUFFER_START_ADDRESS-CMA_START_ADDRESS));

    // カメラのカラーデータをbmp_dataにをコピー(その際にBMPのデータは左下から始まる)
    for (i=0; i<VERTICAL_LINES; i++){
        for (j=0; j<HORIZONTAL_PIXEL; j++){
            bmp_data[(VERTICAL_LINES-1)-i][j].red = (fb_base_addr[i*HORIZONTAL_PIXEL+j]>>16)&0xff;
            bmp_data[(VERTICAL_LINES-1)-i][j].green = (fb_base_addr[i*HORIZONTAL_PIXEL+j]>>8)&0xff;
            bmp_data[(VERTICAL_LINES-1)-i][j].blue = (fb_base_addr[i*HORIZONTAL_PIXEL+j])&0xff;
        }
    }

    // BMPファイルのファイルヘッダに値を代入
    bmpfh.bfType = 0x4d42;
    bmpfh.bfSize = HORIZONTAL_PIXEL*VERTICAL_LINES*3+54;
    bmpfh.bfReserved1 = 0;
    bmpfh.bfReserved2 = 0;
    bmpfh.bfOffBits = 0x36;
    // BMPファイルのINFOヘッダに値を代入
    bmpih.biSize = 0x28;
    bmpih.biWidth = HORIZONTAL_PIXEL;
    bmpih.biHeight = VERTICAL_LINES;
    bmpih.biPlanes = 0x1;
    bmpih.biBitCount = 24;
    bmpih.biCompression = 0;
    bmpih.biSizeImage = 0;
    bmpih.biXPixPerMeter = 3779;
    bmpih.biYPixPerMeter = 3779;
    bmpih.biClrUsed = 0;
    bmpih.biClrImporant = 0;
    
    // bmpファイルに書き出す
    if ((fbmp=fopen(bmp_file, "wb")) == NULL){
        fprintf(stderr, "%s がバイナリ・ライトモードで開けません\n", bmp_file);
        exit(1);
    }
    // BMPファイルヘッダの書き込み
    fwrite(&bmpfh.bfType, sizeof(char), 2, fbmp);
    fwrite(&bmpfh.bfSize, sizeof(long), 1, fbmp);
    fwrite(&bmpfh.bfReserved1, sizeof(short), 1, fbmp);
    fwrite(&bmpfh.bfReserved2, sizeof(short), 1, fbmp);
    fwrite(&bmpfh.bfOffBits, sizeof(long), 1, fbmp);
    // BMPファイルのINFOヘッダの書き込み
    fwrite(&bmpih, sizeof(BITMAPINFOHEADER), 1, fbmp);
    // bmp_dataの書き込み
    for (i=0; i<VERTICAL_LINES; i++) {
        for (j=0; j<HORIZONTAL_PIXEL; j++) {
            fputc((int)bmp_data[i][j^1].blue, fbmp);
            fputc((int)bmp_data[i][j^1].green, fbmp);
            fputc((int)bmp_data[i][j^1].red, fbmp);
        }
    }
    fclose(fbmp);
    for(i=0; i<VERTICAL_LINES; i++){
        free(bmp_data[i]);
    }
    free(bmp_data);
    munmap((void *)frame_buffer, 0x1000000);

    return 0;
}


bmpheader.h を下に示す。

//
// bmpheader.h
// 2014/11/24
//
// reference : http://www.kk.iij4u.or.jp/~kondo/bmp/
//

#include <stdio.h>

// BITMAPFILEHEADER 14bytes
typedef struct tagBITMAPFILEHEADER {
  unsigned short bfType;
  unsigned long  bfSize;
  unsigned short bfReserved1;
  unsigned short bfReserved2;
  unsigned long  bfOffBits;
} BITMAPFILEHEADER;

// BITMAPINFOHEADER 40bytes
typedef struct tagBITMAPINFOHEADER{
    unsigned long  biSize;
    long           biWidth;
    long           biHeight;
    unsigned short biPlanes;
    unsigned short biBitCount;
    unsigned long  biCompression;
    unsigned long  biSizeImage;
    long           biXPixPerMeter;
    long           biYPixPerMeter;
    unsigned long  biClrUsed;
    unsigned long  biClrImporant;
} BITMAPINFOHEADER;

typedef struct BMP24bitsFORMAT {
    unsigned char blue;
    unsigned char green;
    unsigned char red;
} BMP24FORMAT;

  1. 2014年11月25日 05:03 |
  2. ZYBO
  3. | トラックバック:0
  4. | コメント:0

コメント

コメントの投稿


管理者にだけ表示を許可する

トラックバック URL
https://marsee101.blog.fc2.com/tb.php/2988-623f4506
この記事にトラックバックする(FC2ブログユーザー)