Başlangıç > Donanım/Yazılım > Video 4 Linux 2 (v4l2) Bölüm 0

Video 4 Linux 2 (v4l2) Bölüm 0

Bu bölüm konuya giriş niteliğinde olacak. Bu yüzden kullanacağım araçları tanıtacak, biraz teknik bilgi verecek ve işimizi kolaylaştıracak bmp dosya kaydedicisini kodlayacağız.

Geliştirme ortamı olarak Banana Pi M1+ ve OV5640 kamera kullanıyorum. Fakat siz üzerinde linux işletim sistemi ve kamera bulunan herhangi bir sistem üzerinde çalışabilirsiniz (Raspberry Pi, Orange Pi, linux PC gibi).

Windows üzerinde çalıştığımdan linux dosya sisteminde gezinmek için WinSCP kullanıyorum.

https://winscp.net/eng/download.php

adresinden indirebilirsiniz. Bu program kayıt edeceğimiz resim dosyalarını kolayca windows ortamına sürükle bırak şeklinde aktarıp, resim dosyasını windows ile kolayca açabilmemizi sağlayacak.

Notepad++ sı ise editör olarak kullanacağız.

https://notepad-plus-plus.org

adresinden indirebilirsiniz. WinSCP içerisinde Notepad++ sı editör olarak seçtiğinizde birbirlerine çok uyumlu bir geliştirme ortamı oluşturabiliyorsunuz.

Linux bilgisayarınızın internet bağlantısı olduğundan emin olduktan sonra v4l2 ve C derleyici yükleyin.

apt-get install libv4l-dev v4l-utils libav-tools

apt-get install gcc

Sonra sürücüleri çalıştırın. Banana Pi kullananlar aşağıdaki modülleri yüklemeleri gerekir. Başka bir platformda çalışanlar için modül isimleri farklı olabilir veya boot anında çağırıldıklarından kullanıcı müdahelesi gerekmeyebilir.

modprobe ov5640

modprobe sun4i_csi

Sisteminize monitör veya LCD bağlı ise kod yazmaya başlamadan öncede media player yükleyip sürücülerin ve kameranın çalıştığından emin olun.

apt-get install mplayer

Aşağıdaki komut kameradan gelen görüntüyü ekrana aktaracaktır.

mplayer tv://

Herhangi bir görüntü alamadıysanız, kameranın bağlantılarını ve yukarıda anlatılan işlemleri gözden geçirin.

Bundan sonra elde ettiğimiz görüntüleri windows tarafından tanınacak bir formata çevirmemiz de gerekecek. Çünkü OV5640 bize sadece RGB veya YUV formatında data verecek. Ben YUV üzerinden gidip işi biraz daha karıştırıp ileriki bölümlerde YUV hakkındada daha çok teknik bilgi vermeye çalışacağım.

Kameradan elde edeceğimiz datayı bmp formatına çevireceğiz. Bmp dosya formatı kabaca üç katmandan oluşuyor. İlk katmanda dosya ile ilgili bilgiler yer alıyor. İkinici katmanda ise resim ile ilgili bilgiler yer alıyor. Üçüncü yani sonuncu katmanda ise RGB data bilgisi yer alıyor. Aşağıdaki resimde katmanlar ve içerikleri ayrıntılı bir şekilde gösterilmiştir.

zad_vga_tab_struktura

Aşağıda verilen bmp.c ve bmp.h dosyalarını bmp uzantılı dosya oluşturmak için kullanacağız.


#ifndef _BMP_H
#define _BMP_H

#include <stdint.h>

typedef struct
{
unsigned short Signature;
unsigned int FileSize;
unsigned int Reserved;
unsigned int DataOffset;
}__attribute__((__packed__)) Header;

typedef struct
{
unsigned int Size;
unsigned int Width;
unsigned int Height;
unsigned short Planes;
unsigned short BitCount;
unsigned int Compression;
unsigned int ImageSize;
unsigned int HorizontalPixelsPerMeter;
unsigned int VerticalPixelsPerMeter;
unsigned int ColorsUsed;
unsigned int ImportantColors;
}__attribute__((__packed__)) Info;

typedef struct
{
unsigned char Red;
unsigned char Green;
unsigned char Blue;
}__attribute__((__packed__)) Color;

void vSaveImageAsBMP(const char *, unsigned int, unsigned int, const unsigned char *);
void vSaveLuminanceAsBMP(const char *, unsigned int, unsigned int, const unsigned char *);
void vSaveYuvAsBMP(const char *, unsigned int, unsigned int, const unsigned char *);

#endif

 

#include <string.h>
#include <stdio.h>
#include <stdlib.h>

#include "bmp.h"

void vSaveImageAsBMP( const char *FileName,
unsigned int ImageWidth,
unsigned int ImageHeight,
const unsigned char *Image)
{
FILE *FileHandle;
Header BMPheader;
Info BMPInfo;
Color BMPColor;
int i;

unsigned int Width = ImageWidth;
unsigned int Height = ImageHeight;

//BMP header
BMPheader.Signature = 0x4D42;
BMPheader.FileSize = (Width*3+0)*Height + sizeof(Header) + sizeof(Info); //total file size
BMPheader.Reserved = 0;
BMPheader.DataOffset = sizeof(Header) + sizeof(Info);

//BMP info
BMPInfo.Size = sizeof(Info);
BMPInfo.Width = Width;
BMPInfo.Height = Height;
BMPInfo.Planes = 1;
BMPInfo.BitCount = 24; //24bit RGB
BMPInfo.Compression = 0; //no compression
BMPInfo.ImageSize = (Width*3+0)*Height;
BMPInfo.HorizontalPixelsPerMeter = 0;
BMPInfo.VerticalPixelsPerMeter = 0;
BMPInfo.ColorsUsed = 0;
BMPInfo.ImportantColors = 0;

FileHandle = fopen(FileName, "w");

fwrite((const void *)&BMPheader, sizeof(Header), 1, FileHandle);
fwrite((const void *)&BMPInfo, sizeof(Info), 1, FileHandle);

for(i=Height-1; i>=0; i--)
{
fwrite(Image+i*Width*3, Width*3, 1, FileHandle);
}

fclose(FileHandle);
}

void vSaveLuminanceAsBMP( const char *FileName,
unsigned int ImageWidth,
unsigned int ImageHeight,
const unsigned char *Image)
{
FILE *FileHandle;
Header BMPheader;
Info BMPInfo;
Color BMPColor;
int i, j;

unsigned int Width = ImageWidth;
unsigned int Height = ImageHeight;

//BMP header
BMPheader.Signature = 0x4D42;
BMPheader.FileSize = (Width*3+0)*Height + sizeof(Header) + sizeof(Info); //total file size
BMPheader.Reserved = 0;
BMPheader.DataOffset = sizeof(Header) + sizeof(Info);

//BMP info
BMPInfo.Size = sizeof(Info);
BMPInfo.Width = Width;
BMPInfo.Height = Height;
BMPInfo.Planes = 1;
BMPInfo.BitCount = 24; //24bit RGB
BMPInfo.Compression = 0; //no compression
BMPInfo.ImageSize = (Width*3+0)*Height;
BMPInfo.HorizontalPixelsPerMeter = 0;
BMPInfo.VerticalPixelsPerMeter = 0;
BMPInfo.ColorsUsed = 0;
BMPInfo.ImportantColors = 0;

FileHandle = fopen(FileName, "w");

fwrite((const void *)&BMPheader, sizeof(Header), 1, FileHandle);
fwrite((const void *)&BMPInfo, sizeof(Info), 1, FileHandle);

for(i=Height-1; i>=0; i--)
{
for(j=0; j<Width; j++)
fprintf(FileHandle, "%c%c%c", *(Image+i*Width+j), *(Image+i*Width+j), *(Image+i*Width+j));
}

fclose(FileHandle);
}

void vSaveYuvAsBMP( const char *FileName,
unsigned int ImageWidth,
unsigned int ImageHeight,
const unsigned char *Image)
{
int i, j;
void *YUVImage = malloc(ImageWidth*ImageHeight*2 + 1);
void *RGBImage = malloc(ImageWidth*ImageHeight*3 + 1);
unsigned char *ptrYUVImage = (unsigned char *)YUVImage;
unsigned char *ptrRGBImage = (unsigned char *)RGBImage;
float R, G, B;
int Y, U, V;

memcpy(YUVImage, Image, ImageWidth*ImageHeight*2);

for(i=0; i<ImageWidth*ImageHeight; i++)
{

Y = *ptrYUVImage;
U = *(ptrYUVImage+ImageWidth*ImageHeight-i/2-i%2);
V = *(ptrYUVImage+3*ImageWidth*ImageHeight/2-i/2-i%2);

Y -=0; U-=128; V-=128;

R = 1.164*Y + 0.000*U + 1.596*V;
G = 1.164*Y - 0.391*U - 0.813*V;
B = 1.164*Y + 2.018*U + 0.000*V;

if(R > 255.0) R = 255.0; if(R < 0.0) R =0.0;
if(G > 255.0) G = 255.0; if(G < 0.0) G =0.0;
if(B > 255.0) B = 255.0; if(B < 0.0) B =0.0;

ptrYUVImage++;
*ptrRGBImage++ = B;
*ptrRGBImage++ = G;
*ptrRGBImage++ = R;

}

vSaveImageAsBMP(FileName, ImageWidth, ImageHeight, RGBImage);

free(YUVImage);
free(RGBImage);
}

Ufak da bir deneme yapalım. 400×400 boyutlarında içerisinde renk barları olan bir veri bloğu oluşturalım ve bu bloğu bmp ye çevirelim.


#include <string.h>
#include <stdio.h>
#include <stdlib.h>

#include "bmp.h"

#define IMAGE_WIDTH 400
#define IMAGE_HEIGHT 400
#define NUMBER_OF_COLOR_BARS 8
#define COLOR_BARS_HEIGHT (IMAGE_HEIGHT/NUMBER_OF_COLOR_BARS)

int main()
{
int i, j, BarColor = 0;
unsigned char R, G, B;
void *Image = calloc(IMAGE_WIDTH*IMAGE_HEIGHT*3,sizeof(char));
unsigned char *Pixel = (unsigned char *)Image;

//create test image
for(i=0; i<NUMBER_OF_COLOR_BARS; i++)
{
for(j=0; j<IMAGE_WIDTH*COLOR_BARS_HEIGHT; j++)
{
switch(BarColor)
{
case 0: R=0x00; G=0x00; B=0x00; break;
case 1: R=0xFF; G=0x00; B=0x00; break;
case 2: R=0x00; G=0xFF; B=0x00; break;
case 3: R=0x00; G=0x00; B=0xFF; break;
case 4: R=0xFF; G=0xFF; B=0x00; break;
case 5: R=0x00; G=0xFF; B=0xFF; break;
case 6: R=0xFF; G=0x00; B=0xFF; break;
case 7: R=0xFF; G=0xFF; B=0xFF; break;
}
*Pixel++ = B;
*Pixel++ = G;
*Pixel++ = R;
}
BarColor++;
}

vSaveImageAsBMP("testimage.bmp", IMAGE_WIDTH, IMAGE_HEIGHT, Image);
free(Image);
return 0;
}

Derlemek için

gcc main.c bmp.c -o bmpmaker

Çalıştırmak için

./bmpmaker

Oluşturulan resim dosyasını (testimage.bmp) windows da açdığımızda (WinSCP ile aktarıp) aşağıdaki görüntüyü almalıyız.

testimage

Devam edecek…

 

Reklamlar
Kategoriler:Donanım/Yazılım

Bir Cevap Yazın

Aşağıya bilgilerinizi girin veya oturum açmak için bir simgeye tıklayın:

WordPress.com Logosu

WordPress.com hesabınızı kullanarak yorum yapıyorsunuz. Çıkış  Yap / Değiştir )

Twitter resmi

Twitter hesabınızı kullanarak yorum yapıyorsunuz. Çıkış  Yap / Değiştir )

Facebook fotoğrafı

Facebook hesabınızı kullanarak yorum yapıyorsunuz. Çıkış  Yap / Değiştir )

Google+ fotoğrafı

Google+ hesabınızı kullanarak yorum yapıyorsunuz. Çıkış  Yap / Değiştir )

Connecting to %s

%d blogcu bunu beğendi: