#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <string.h>
using namespace cv;
#define PIXEL_NUM_OF_BYTES 4
#define NUMBER_OF_WRITE_FRAMES 3 // Note: If not at least 3 or more, the image is not displayed in succession.
#define XGA_HORIZONTAL_PIXELS 1024
#define XGA_VERTICAL_LINES 768
#define XGA_ALL_DISP_ADDRESS (XGA_HORIZONTAL_PIXELS * XGA_VERTICAL_LINES * PIXEL_NUM_OF_BYTES)
#define XGA_3_PICTURES (XGA_ALL_DISP_ADDRESS * NUMBER_OF_WRITE_FRAMES)
#define SVGA_HORIZONTAL_PIXELS 800
#define SVGA_VERTICAL_LINES 600
#define SVGA_ALL_DISP_ADDRESS (SVGA_HORIZONTAL_PIXELS * SVGA_VERTICAL_LINES * PIXEL_NUM_OF_BYTES)
#define SVGA_3_PICTURES (SVGA_ALL_DISP_ADDRESS * NUMBER_OF_WRITE_FRAMES)
static void print_help()
{
/* if(argc < 3)
{
print_help();
return 0;
} */
for( int i = 1; i < argc; i++ )
{
if ( argv[i][0] == '-' && argv[i][1] == 'h')
{
print_help();
return 0;
}
}
StereoBM bm;
StereoSGBM sgbm;
StereoVar var;
// Start by marsee
unsigned char attr[1024];
unsigned long phys_addr;
// udmabuf0
int fdf = open("/dev/udmabuf0", O_RDWR | O_SYNC); // frame_buffer, The cache is disabled.
if (fdf == -1){
fprintf(stderr, "/dev/udmabuf0 open error\n");
exit(-1);
}
volatile unsigned *frame_buffer = (volatile unsigned *)mmap(NULL, SVGA_3_PICTURES+XGA_3_PICTURES+SVGA_ALL_DISP_ADDRESS, PROT_READ|PROT_WRITE, MAP_SHARED, fdf, 0);
if (!frame_buffer){
fprintf(stderr, "frame_buffer mmap error\n");
exit(-1);
}
// phys_addr of udmabuf0
int fdp = open("/sys/devices/virtual/udmabuf/udmabuf0/phys_addr", O_RDONLY);
if (fdp == -1){
fprintf(stderr, "/sys/devices/virtual/udmabuf/udmabuf0/phys_addr open error\n");
exit(-1);
}
read(fdp, attr, 1024);
sscanf((const char *)attr, "%lx", &phys_addr);
close(fdp);
printf("phys_addr = %x\n", (unsigned int)phys_addr);
// End by marsee
for( int i = 1; i < argc; i++ )
{
/*if( !img1_filename || !img2_filename )
{
printf("Command-line parameter error: both left and right images must be specified\n");
return -1;
} */
int color_mode = alg == STEREO_BM ? 0 : -1;
//Mat img1 = imread(img1_filename, color_mode);
//Mat img2 = imread(img2_filename, color_mode);
// Start by marsee
Mat imgL_t(Size(800, 600), CV_8UC3);
Mat imgR_t(Size(800, 600), CV_8UC3);
volatile unsigned int *Leye_addr = frame_buffer; // The Left Camera Image
volatile unsigned int *Reye_addr = (volatile unsigned int *)((unsigned)frame_buffer+SVGA_3_PICTURES+0x8); // The Right Camera Image
// Copy "Left Camera Image" to Mat
for (int y=0; y<imgL_t.rows; y++){
Vec3b* ptr = imgL_t.ptr<Vec3b>(y);
for (int x=0; x<imgL_t.cols; x++){
int blue = Leye_addr[y*imgL_t.cols+x] & 0xff;
int green = (Leye_addr[y*imgL_t.cols+x] & 0xff00)>>8;
int red = (Leye_addr[y*imgL_t.cols+x] & 0xff0000)>>16;
ptr[x] = Vec3b(blue, green, red);
}
}
// Copy "Right Camera Image" to Mat
for (int y=0; y<imgR_t.rows; y++){
Vec3b* ptr = imgR_t.ptr<Vec3b>(y);
for (int x=0; x<imgR_t.cols; x++){
int blue = Reye_addr[y*imgR_t.cols+x] & 0xff;
int green = (Reye_addr[y*imgR_t.cols+x] & 0xff00)>>8;
int red = (Reye_addr[y*imgR_t.cols+x] & 0xff0000)>>16;
ptr[x] = Vec3b(blue, green, red);
}
}
Mat img1(Size(640, 480), CV_8UC3);
Mat img2(Size(640, 480), CV_8UC3);
resize(imgL_t, img1, img1.size(), 0, 0, INTER_CUBIC);
resize(imgR_t, img2, img2.size(), 0, 0, INTER_CUBIC);
// End by marsee
if( scale != 1.f )
{
do {
// user が 1になった時にフレームがスタートする
ins >> pix;
} while(pix.user == 0);
//
// lap_filter_axis.cpp
// 2015/05/01
// 2015/06/25 : 修正、ラプラシアンフィルタの値が青だけ担っていたので、RGBに拡張した
// 2016/03/23 : hls::LineBuffer, hls::Window を使用した
//
#include <stdio.h>
#include <string.h>
#include <ap_int.h>
#include <hls_stream.h>
#include <ap_axi_sdata.h>
#include <hls_video.h>
#include "lap_filter_axis.h"
int conv_rgb2y(int rgb);
int lap_filter_axis(hls::stream<ap_axis<32,1,1,1> >& ins, hls::stream<ap_axis<32,1,1,1> >& outs){
#pragma HLS INTERFACE axis port=ins
#pragma HLS INTERFACE axis port=outs
#pragma HLS INTERFACE s_axilite port=return
ap_axis<32,1,1,1> pix;
ap_axis<32,1,1,1> lap;
hls::LineBuffer<2, HORIZONTAL_PIXEL_WIDTH, int> linebuf;
hls::Window<3, 3, int> mbuf;
int gray_pix, val, i, j, x, y;
const int lap_weight[3][3] = {{-1, -1, -1},{-1, 8, -1},{-1, -1, -1}};
do { // user が 1になった時にフレームがスタートする
ins >> pix;
} while(pix.user == 0);
for (y=0; y<VERTICAL_PIXEL_WIDTH; y++){
for (x=0; x<HORIZONTAL_PIXEL_WIDTH; x++){
#pragma HLS PIPELINE II=1
if (!(x==0 && y==0)) // 最初の入力はすでに入力されている
ins >> pix; // AXI4-Stream からの入力
mbuf.shift_left(); // mbuf の列を1ビット左シフト
mbuf.insert(linebuf(1,x), 2, 2);
mbuf.insert(linebuf(0,x), 1, 2);
gray_pix = conv_rgb2y(pix.data);
mbuf.insert(gray_pix, 0, 2);
// LineBuffer の更新
linebuf.shift_down(x);
linebuf.insert_bottom(gray_pix, x);
// ラプラシアンフィルタの演算
for (j=0, val=0; j<3; j++){
for (i=0; i<3; i++){
val += lap_weight[j][i] * mbuf(2-j,i);
}
}
if (val<0) // 飽和演算
val = 0;
else if (val>255)
val = 255;
lap.data = (val<<16)+(val<<8)+val;
if (x<2 || y<2) // 最初の2行とその他の行の最初の2列は無効データなので0とする
lap.data = 0;
if (x==0 && y==0) // 最初のデータでは、TUSERをアサートする
lap.user = 1;
else
lap.user = 0;
if (x == (HORIZONTAL_PIXEL_WIDTH-1)) // 行の最後で TLAST をアサートする
lap.last = 1;
else
lap.last = 0;
outs << lap; // AXI4-Stream へ出力
}
}
return(0);
}
// RGBからYへの変換
// RGBのフォーマットは、{8'd0, R(8bits), G(8bits), B(8bits)}, 1pixel = 32bits
// 輝度信号Yのみに変換する。変換式は、Y = 0.299R + 0.587G + 0.114B
// "YUVフォーマット及び YUV<->RGB変換"を参考にした。http://vision.kuee.kyoto-u.ac.jp/~hiroaki/firewire/yuv.html
// 2013/09/27 : float を止めて、すべてint にした
int conv_rgb2y(int rgb){
int r, g, b, y_f;
int y;
b = rgb & 0xff;
g = (rgb>>8) & 0xff;
r = (rgb>>16) & 0xff;
y_f = 77*r + 150*g + 29*b; //y_f = 0.299*r + 0.587*g + 0.114*b;の係数に256倍した
y = y_f >> 8; // 256で割る
return(y);
}
int lap_filter_axim(volatile int *cam_fb, volatile int *lap_fb)
{
#pragma HLS INTERFACE s_axilite port=return
#pragma HLS INTERFACE m_axi depth=3072 port=cam_fb offset=slave bundle=cam_fb
#pragma HLS INTERFACE m_axi depth=3072 port=lap_fb offset=slave bundle=lap_fb
hls::LineBuffer<2, HORIZONTAL_PIXEL_WIDTH, int> linebuf;
hls::Window<3, 3, int> mbuf;
int x, y;
int val;
int gray_pix;
int i, j;
const int lap_weight[3][3] = {{-1, -1, -1},{-1, 8, -1},{-1, -1, -1}};
#pragma HLS ARRAY_PARTITION variable=lap_weight complete dim=0
int read_line[HORIZONTAL_PIXEL_WIDTH];
int write_line[HORIZONTAL_PIXEL_WIDTH];
// RGB値をY(輝度成分)のみに変換し、ラプラシアンフィルタを掛けた。
for (y=0; y<VERTICAL_PIXEL_WIDTH; y++){
for(i=0; i<HORIZONTAL_PIXEL_WIDTH; i++){
read_line[i] = cam_fb[y*(HORIZONTAL_PIXEL_WIDTH)+i];
}
for (x=0; x<HORIZONTAL_PIXEL_WIDTH; x++){
mbuf.shift_left(); // mbuf の列を1ビット左シフト
//mbuf.insert_left(colbuf); // mbuf の列に colbuf[] を代入
mbuf.insert(linebuf(1,x), 2, 2);
mbuf.insert(linebuf(0,x), 1, 2);
gray_pix = conv_rgb2y(read_line[x]);
mbuf.insert(gray_pix, 0, 2);
// LineBuffer の更新
linebuf.shift_down(x);
linebuf.insert_bottom(gray_pix, x);
// ラプラシアンフィルタの演算
for (j=0, val=0; j<3; j++){
for (i=0; i<3; i++){
val += lap_weight[j][i] * mbuf(2-j,i);
}
}
if (val<0) // 飽和演算
val = 0;
else if (val>255)
val = 255;
// ラプラシアンフィルタ・データの書き込み
if (x>1 && y>1)
write_line[x] = (val<<16)+(val<<8)+val ;
else
// x<2 || y<2 の場合はピクセルデータがまだ揃っていないので0にする
write_line[x] = 0;
// printf("x = %d y = %d", x, y);
}
for (i=0; i<HORIZONTAL_PIXEL_WIDTH; i++){
lap_fb[y*(HORIZONTAL_PIXEL_WIDTH)+i] = write_line[i];
}
}
return(0);
}
int lap_filter_axim(volatile int *cam_fb, volatile int *lap_fb)
{
#pragma HLS INTERFACE s_axilite port=return
#pragma HLS INTERFACE m_axi depth=3072 port=cam_fb offset=slave bundle=cam_fb
#pragma HLS INTERFACE m_axi depth=3072 port=lap_fb offset=slave bundle=lap_fb
hls::LineBuffer<2, HORIZONTAL_PIXEL_WIDTH, int> linebuf;
hls::Window<3, 3, int> mbuf;
int x, y;
int val;
int gray_pix;
int i, j;
const int lap_weight[3][3] = {{-1, -1, -1},{-1, 8, -1},{-1, -1, -1}};
#pragma HLS ARRAY_PARTITION variable=lap_weight complete dim=0
int read_line[HORIZONTAL_PIXEL_WIDTH];
int write_line[HORIZONTAL_PIXEL_WIDTH];
// RGB値をY(輝度成分)のみに変換し、ラプラシアンフィルタを掛けた。
for (y=0; y<VERTICAL_PIXEL_WIDTH; y++){
// 1 行 Read
memcpy(read_line, (const int*)&cam_fb[y*(HORIZONTAL_PIXEL_WIDTH)], (HORIZONTAL_PIXEL_WIDTH)*sizeof(int));
for (x=0; x<HORIZONTAL_PIXEL_WIDTH; x++){
mbuf.shift_left(); // mbuf の列を1ビット左シフト
//mbuf.insert_left(colbuf); // mbuf の列に colbuf[] を代入
mbuf.insert(linebuf(1,x), 2, 2);
mbuf.insert(linebuf(0,x), 1, 2);
gray_pix = conv_rgb2y(read_line[x]);
mbuf.insert(gray_pix, 0, 2);
// LineBuffer の更新
linebuf.shift_down(x);
linebuf.insert_bottom(gray_pix, x);
// ラプラシアンフィルタの演算
for (j=0, val=0; j<3; j++){
for (i=0; i<3; i++){
val += lap_weight[j][i] * mbuf(2-j,i);
}
}
if (val<0) // 飽和演算
val = 0;
else if (val>255)
val = 255;
// ラプラシアンフィルタ・データの書き込み
if (x>1 && y>1)
write_line[x] = (val<<16)+(val<<8)+val ;
else
// x<2 || y<2 の場合はピクセルデータがまだ揃っていないので0にする
write_line[x] = 0;
// printf("x = %d y = %d", x, y);
}
memcpy((void *)&lap_fb[y*(HORIZONTAL_PIXEL_WIDTH)], (const int*)write_line, (HORIZONTAL_PIXEL_WIDTH)*sizeof(int));
}
return(0);
}
int lap_filter_axim(volatile int *cam_fb, volatile int *lap_fb)
{
#pragma HLS INTERFACE s_axilite port=return
#pragma HLS INTERFACE m_axi depth=3072 port=cam_fb offset=slave bundle=cam_fb
#pragma HLS INTERFACE m_axi depth=3072 port=lap_fb offset=slave bundle=lap_fb
hls::LineBuffer<2, HORIZONTAL_PIXEL_WIDTH, int> linebuf;
hls::Window<3, 3, int> mbuf;
int x, y;
int val;
int gray_pix;
int i, j;
const int lap_weight[3][3] = {{-1, -1, -1},{-1, 8, -1},{-1, -1, -1}};
#pragma HLS ARRAY_PARTITION variable=lap_weight complete dim=0
int read_line[HORIZONTAL_PIXEL_WIDTH];
int write_line[HORIZONTAL_PIXEL_WIDTH];
// RGB値をY(輝度成分)のみに変換し、ラプラシアンフィルタを掛けた。
for (y=0; y<VERTICAL_PIXEL_WIDTH; y++){
for (x=0; x<HORIZONTAL_PIXEL_WIDTH; x++){
if (x == 0) // 1 行 Read
memcpy(read_line, (const int*)&cam_fb[y*(HORIZONTAL_PIXEL_WIDTH)], (HORIZONTAL_PIXEL_WIDTH)*sizeof(int));
mbuf.shift_left(); // mbuf の列を1ビット左シフト
mbuf.insert(linebuf(1,x), 2, 2);
mbuf.insert(linebuf(0,x), 1, 2);
gray_pix = conv_rgb2y(read_line[x]);
mbuf.insert(gray_pix, 0, 2);
// LineBuffer の更新
linebuf.shift_down(x);
linebuf.insert_bottom(gray_pix, x);
// ラプラシアンフィルタの演算
for (j=0, val=0; j<3; j++){
for (i=0; i<3; i++){
val += lap_weight[j][i] * mbuf(2-j,i);
}
}
if (val<0) // 飽和演算
val = 0;
else if (val>255)
val = 255;
// ラプラシアンフィルタ・データの書き込み
if (x>1 && y>1)
write_line[x] = (val<<16)+(val<<8)+val ;
else
// x<2 || y<2 の場合はピクセルデータがまだ揃っていないので0にする
write_line[x] = 0;
// printf("x = %d y = %d", x, y);
if (x == (HORIZONTAL_PIXEL_WIDTH-1))
memcpy((void *)&lap_fb[y*(HORIZONTAL_PIXEL_WIDTH)], (const int*)write_line, (HORIZONTAL_PIXEL_WIDTH)*sizeof(int));
}
}
return(0);
}
%YAML:1.0
R: !!opencv-matrix
rows: 3
cols: 3
dt: d
data: [ 9.9946469358847922e-01, -1.1180576509711158e-02,
3.0746072578428339e-02, 1.0477412330910473e-02,
9.9968201221380104e-01, 2.2936832541000249e-02,
-3.0992742713989885e-02, -2.2602415027520792e-02,
9.9926401953337052e-01 ]
T: !!opencv-matrix
rows: 3
cols: 1
dt: d
data: [ -6.4327525053555608e+00, 4.9819569385123899e-02,
1.5248276562670204e-01 ]
R1: !!opencv-matrix
rows: 3
cols: 3
dt: d
data: [ 9.9980738074161812e-01, -1.8381302616960832e-02,
6.8796168998461159e-03, 1.8300896985381197e-02,
9.9976553851253258e-01, 1.1573468463524205e-02,
-7.0907393207904693e-03, -1.1445336030428873e-02,
9.9990935874159870e-01 ]
R2: !!opencv-matrix
rows: 3
cols: 3
dt: d
data: [ 9.9968921220119289e-01, -7.7422667869396578e-03,
-2.3696757448185279e-02, 7.4689840041410986e-03,
9.9990483003403074e-01, -1.1599360006570166e-02,
2.3784307568313970e-02, 1.1418764364675654e-02,
9.9965189867967530e-01 ]
P1: !!opencv-matrix
rows: 3
cols: 4
dt: d
data: [ 7.8203511447089386e+02, 0., 3.3787803268432617e+02, 0., 0.,
7.8203511447089386e+02, 2.5315318870544434e+02, 0., 0., 0., 1.,
0. ]
P2: !!opencv-matrix
rows: 3
cols: 4
dt: d
data: [ 7.8203511447089386e+02, 0., 3.3787803268432617e+02,
-5.0322022889612026e+03, 0., 7.8203511447089386e+02,
2.5315318870544434e+02, 0., 0., 0., 1., 0. ]
Q: !!opencv-matrix
rows: 4
cols: 4
dt: d
data: [ 1., 0., 0., -3.3787803268432617e+02, 0., 1., 0.,
-2.5315318870544434e+02, 0., 0., 0., 7.8203511447089386e+02, 0.,
0., 1.5540613623311419e-01, 0. ]
%YAML:1.0
M1: !!opencv-matrix
rows: 3
cols: 3
dt: d
data: [ 8.8235697678477902e+02, 0., 3.2955358227551494e+02, 0.,
8.8235697678477902e+02, 2.5548502946546807e+02, 0., 0., 1. ]
D1: !!opencv-matrix
rows: 1
cols: 8
dt: d
data: [ -3.2775953128095858e-01, -6.5894028034894281e-01, 0., 0., 0.,
0., 0., -6.2343465096598827e+00 ]
M2: !!opencv-matrix
rows: 3
cols: 3
dt: d
data: [ 8.8235697678477902e+02, 0., 3.3256199841666762e+02, 0.,
8.8235697678477902e+02, 2.5216232763526432e+02, 0., 0., 1. ]
D2: !!opencv-matrix
rows: 1
cols: 8
dt: d
data: [ -3.4032226081273226e-01, -1.3685804150694736e+00, 0., 0., 0.,
0., 0., -7.5954408258027808e+00 ]
int lap_filter_axim(volatile int *cam_fb, volatile int *lap_fb)
{
#pragma HLS INTERFACE s_axilite port=return
#pragma HLS INTERFACE m_axi depth=3072 port=cam_fb offset=slave bundle=cam_fb
#pragma HLS INTERFACE m_axi depth=3072 port=lap_fb offset=slave bundle=lap_fb
hls::LineBuffer<2, HORIZONTAL_PIXEL_WIDTH, int> linebuf;
hls::Window<3, 3, int> mbuf;
int x, y;
int val;
int i, j;
const int lap_weight[3][3] = {{-1, -1, -1},{-1, 8, -1},{-1, -1, -1}};
#pragma HLS ARRAY_PARTITION variable=lap_weight complete dim=0
int pix, gray_pix;
// RGB値をY(輝度成分)のみに変換し、ラプラシアンフィルタを掛けた。
for (y=0; y<VERTICAL_PIXEL_WIDTH; y++){
for (x=0; x<HORIZONTAL_PIXEL_WIDTH; x++){
// 1ピクセル読み出し
pix = cam_fb[y*HORIZONTAL_PIXEL_WIDTH+x];
gray_pix = conv_rgb2y(pix);
mbuf.shift_left(); // mbuf の列を1ビット左シフト
//mbuf.insert_left(colbuf); // mbuf の列に colbuf[] を代入
mbuf.insert(linebuf(1,x), 2, 2);
mbuf.insert(linebuf(0,x), 1, 2);
mbuf.insert(gray_pix, 0, 2);
// LineBuffer の更新
linebuf.shift_down(x);
linebuf.insert_bottom(gray_pix, x);
// ラプラシアンフィルタの演算
for (j=0, val=0; j<3; j++){
for (i=0; i<3; i++){
val += lap_weight[j][i] * mbuf(2-j,i);
}
}
if (val<0) // 飽和演算
val = 0;
else if (val>255)
val = 255;
// ラプラシアンフィルタ・データの書き込み
if (x>1 && y>1)
lap_fb[y*HORIZONTAL_PIXEL_WIDTH+x] = (val<<16)+(val<<8)+val ;
else
// x<2 || y<2 の場合はピクセルデータがまだ揃っていないので0にする
lap_fb[y*HORIZONTAL_PIXEL_WIDTH+x] = 0;
// printf("x = %d y = %d", x, y);
}
}
return(0);
}
// Testbench of laplacian_filter.c
// lap_filter_tb.c
// BMPデータをハードウェアとソフトウェアで、ラプラシアン・フィルタを掛けて、それを比較する
// m_axi offset=slave version
// 2015/08/26 by marsee
//
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "gmp.h"
#include "bmp_header.h"
int laplacian_fil_soft(int x0y0, int x1y0, int x2y0, int x0y1, int x1y1, int x2y1, int x0y2, int x1y2, int x2y2);
int conv_rgb2y_soft(int rgb);
int lap_filter_axim(volatile int *cam_fb, volatile int *lap_fb); // hardware
void laplacian_filter_soft(int *cam_fb, int *lap_fb, long width, long height); // software
int main()
{
int *s, *h;
long x, y;
BITMAPFILEHEADER bmpfhr; // BMPファイルのファイルヘッダ(for Read)
BITMAPINFOHEADER bmpihr; // BMPファイルのINFOヘッダ(for Read)
FILE *fbmpr, *fbmpw;
int *rd_bmp, *hw_lapd, *sw_lapd;
int blue, green, red;
char blue_c, green_c, red_c;
if ((fbmpr = fopen("test.bmp", "rb")) == NULL){ // test.bmp をオープン
fprintf(stderr, "Can't open test.bmp by binary read mode\n");
exit(1);
}
// bmpヘッダの読み出し
fread(&bmpfhr.bfType, sizeof(char), 2, fbmpr);
fread(&bmpfhr.bfSize, sizeof(long), 1, fbmpr);
fread(&bmpfhr.bfReserved1, sizeof(short), 1, fbmpr);
fread(&bmpfhr.bfReserved2, sizeof(short), 1, fbmpr);
fread(&bmpfhr.bfOffBits, sizeof(long), 1, fbmpr);
fread(&bmpihr, sizeof(BITMAPINFOHEADER), 1, fbmpr);
// ピクセルを入れるメモリをアロケートする
if ((rd_bmp =(int *)malloc(sizeof(int) * (bmpihr.biWidth * bmpihr.biHeight))) == NULL){
fprintf(stderr, "Can't allocate rd_bmp memory\n");
exit(1);
}
if ((hw_lapd =(int *)malloc(sizeof(int) * (bmpihr.biWidth * bmpihr.biHeight))) == NULL){
fprintf(stderr, "Can't allocate hw_lapd memory\n");
exit(1);
}
if ((sw_lapd =(int *)malloc(sizeof(int) * (bmpihr.biWidth * bmpihr.biHeight))) == NULL){
fprintf(stderr, "Can't allocate sw_lapd memory\n");
exit(1);
}
// rd_bmp にBMPのピクセルを代入。その際に、行を逆転する必要がある
for (y=0; y<bmpihr.biHeight; y++){
for (x=0; x<bmpihr.biWidth; x++){
blue = fgetc(fbmpr);
green = fgetc(fbmpr);
red = fgetc(fbmpr);
rd_bmp[((bmpihr.biHeight-1)-y)*bmpihr.biWidth+x] = (blue & 0xff) | ((green & 0xff)<<8) | ((red & 0xff)<<16);
}
}
fclose(fbmpr);
lap_filter_axim((int *)rd_bmp, (int *)hw_lapd); // ハードウェアのラプラシアン・フィルタ
laplacian_filter_soft(rd_bmp, sw_lapd, bmpihr.biWidth, bmpihr.biHeight); // ソフトウェアのラプラシアン・フィルタ
// ハードウェアとソフトウェアのラプラシアン・フィルタの値のチェック
for (y=0, h=hw_lapd, s=sw_lapd; y<bmpihr.biHeight; y++){
for (x=0; x<bmpihr.biWidth; x++){
//if (*s != 0){
if (*h != *s){
printf("ERROR HW and SW results mismatch x = %ld, y = %ld, HW = %d, SW = %d\n", x, y, *h, *s);
//return(1);
} else {
h++;
s++;
}
}
}
printf("Success HW and SW results match\n");
// ハードウェアのラプラシアンフィルタの結果を temp_lap.bmp へ出力する
if ((fbmpw=fopen("temp_lap.bmp", "wb")) == NULL){
fprintf(stderr, "Can't open temp_lap.bmp by binary write mode\n");
exit(1);
}
// BMPファイルヘッダの書き込み
fwrite(&bmpfhr.bfType, sizeof(char), 2, fbmpw);
fwrite(&bmpfhr.bfSize, sizeof(long), 1, fbmpw);
fwrite(&bmpfhr.bfReserved1, sizeof(short), 1, fbmpw);
fwrite(&bmpfhr.bfReserved2, sizeof(short), 1, fbmpw);
fwrite(&bmpfhr.bfOffBits, sizeof(long), 1, fbmpw);
fwrite(&bmpihr, sizeof(BITMAPINFOHEADER), 1, fbmpw);
// RGB データの書き込み、逆順にする
for (y=0; y<bmpihr.biHeight; y++){
for (x=0; x<bmpihr.biWidth; x++){
blue = hw_lapd[((bmpihr.biHeight-1)-y)*bmpihr.biWidth+x] & 0xff;
green = (hw_lapd[((bmpihr.biHeight-1)-y)*bmpihr.biWidth+x] >> 8) & 0xff;
red = (hw_lapd[((bmpihr.biHeight-1)-y)*bmpihr.biWidth+x]>>16) & 0xff;
fputc(blue, fbmpw);
fputc(green, fbmpw);
fputc(red, fbmpw);
}
}
fclose(fbmpw);
free(rd_bmp);
free(hw_lapd);
free(sw_lapd);
return(0);
}
void laplacian_filter_soft(int *cam_fb, int *lap_fb, long width, long height)
{
int **line_buf;
int *lap_buf;
int x, y, i;
int lap_fil_val;
int a, b;
int fl, sl, tl;
// line_buf の1次元目の配列をアロケートする
if ((line_buf =(int **)malloc(sizeof(int *) * 3)) == NULL){
fprintf(stderr, "Can't allocate line_buf[3][]\n");
exit(1);
}
// メモリをアロケートする
for (i=0; i<3; i++){
if ((line_buf[i]=(int *)malloc(sizeof(int) * width)) == NULL){
fprintf(stderr, "Can't allocate line_buf[%d]\n", i);
exit(1);
}
}
if ((lap_buf=(int *)malloc(sizeof(int) * (width))) == NULL){
fprintf(stderr, "Can't allocate lap_buf memory\n");
exit(1);
}
// RGB値をY(輝度成分)のみに変換し、ラプラシアンフィルタを掛けた。
for (y=0; y<height; y++){
for (x=0; x<width; x++){
// 1つのピクセルを読み込みながらラプラシアン・フィルタを実行する
line_buf[y%3][x] = cam_fb[(y*width)+x];
line_buf[y%3][x] = conv_rgb2y_soft(line_buf[y%3][x]);
if ((y < 2) || (x < 2)){
lap_fb[(y*width)+x] = 0;
continue;
}
fl = (y+1)%3; // 最初のライン, y=2 012, y=3 120, y=4 201
sl = (y+2)%3; // 2番めのライン
tl = (y+3)%3; // 3番目のライン
lap_fil_val = laplacian_fil_soft(line_buf[fl][x-2], line_buf[fl][x-1], line_buf[fl][x], line_buf[sl][x-2], line_buf[sl][x-1], line_buf[sl][x], line_buf[tl][x-2], line_buf[tl][x-1], line_buf[tl][x]);
// ラプラシアンフィルタ・データの書き込み
lap_fb[(y*width)+x] = (lap_fil_val<<16)+(lap_fil_val<<8)+lap_fil_val ;
// printf("x = %d y = %d", x, y);
}
}
free(lap_buf);
for (i=0; i<3; i++)
free(line_buf[i]);
free(line_buf);
}
// RGBからYへの変換
// RGBのフォーマットは、{8'd0, R(8bits), G(8bits), B(8bits)}, 1pixel = 32bits
// 輝度信号Yのみに変換する。変換式は、Y = 0.299R + 0.587G + 0.114B
// "YUVフォーマット及び YUV<->RGB変換"を参考にした。http://vision.kuee.kyoto-u.ac.jp/~hiroaki/firewire/yuv.html
// 2013/09/27 : float を止めて、すべてint にした
int conv_rgb2y_soft(int rgb){
int r, g, b, y_f;
int y;
b = rgb & 0xff;
g = (rgb>>8) & 0xff;
r = (rgb>>16) & 0xff;
y_f = 77*r + 150*g + 29*b; //y_f = 0.299*r + 0.587*g + 0.114*b;の係数に256倍した
y = y_f >> 8; // 256で割る
return(y);
}
// ラプラシアンフィルタ
// x0y0 x1y0 x2y0 -1 -1 -1
// x0y1 x1y1 x2y1 -1 8 -1
// x0y2 x1y2 x2y2 -1 -1 -1
int laplacian_fil_soft(int x0y0, int x1y0, int x2y0, int x0y1, int x1y1, int x2y1, int x0y2, int x1y2, int x2y2)
{
int y;
y = -x0y0 -x1y0 -x2y0 -x0y1 +8*x1y1 -x2y1 -x0y2 -x1y2 -x2y2;
if (y<0)
y = 0;
else if (y>255)
y = 255;
return(y);
}
// lap_filter_axim_lb.cpp
// m_axi offset=slave Version
// 2016/03/12 : hls::LineBuffer, hls::Window を使用した
//
#include <stdio.h>
#include <string.h>
#include <hls_video.h>
#define HORIZONTAL_PIXEL_WIDTH 64
#define VERTICAL_PIXEL_WIDTH 48
//#define HORIZONTAL_PIXEL_WIDTH 800
//#define VERTICAL_PIXEL_WIDTH 600
#define ALL_PIXEL_VALUE (HORIZONTAL_PIXEL_WIDTH*VERTICAL_PIXEL_WIDTH)
int conv_rgb2y(int rgb);
int lap_filter_axim(volatile int *cam_fb, volatile int *lap_fb)
{
#pragma HLS INTERFACE s_axilite port=return
#pragma HLS INTERFACE m_axi depth=3072 port=cam_fb offset=slave bundle=cam_fb
#pragma HLS INTERFACE m_axi depth=3072 port=lap_fb offset=slave bundle=lap_fb
hls::LineBuffer<2, HORIZONTAL_PIXEL_WIDTH, int> linebuf;
hls::Window<3, 3, int> mbuf;
int x, y;
int val;
int t_val;
int i, j;
const int lap_weight[3][3] = {{-1, -1, -1},{-1, 8, -1},{-1, -1, -1}};
#pragma HLS ARRAY_PARTITION variable=lap_weight complete dim=0
int pix;
// RGB値をY(輝度成分)のみに変換し、ラプラシアンフィルタを掛けた。
for (y=0; y<VERTICAL_PIXEL_WIDTH; y++){
for (x=0; x<HORIZONTAL_PIXEL_WIDTH; x++){
// 1ピクセル読み出し
pix = cam_fb[y*HORIZONTAL_PIXEL_WIDTH+x];
mbuf.shift_left(); // mbuf の列を1ビット左シフト
mbuf.insert(linebuf(1,x), 2, 2);
mbuf.insert(linebuf(0,x), 1, 2);
mbuf.insert(pix, 0, 2);
// LineBuffer の更新
linebuf.shift_down(x);
linebuf.insert_bottom(pix, x);
// ラプラシアンフィルタの演算
for (j=0, val=0; j<3; j++){
for (i=0; i<3; i++){
t_val = mbuf(2-j,i);
val += lap_weight[j][i] * conv_rgb2y(t_val);
}
}
if (val<0) // 飽和演算
val = 0;
else if (val>255)
val = 255;
// ラプラシアンフィルタ・データの書き込み
if (x>1 && y>1)
lap_fb[y*HORIZONTAL_PIXEL_WIDTH+x] = (val<<16)+(val<<8)+val ;
else
// x<2 || y<2 の場合はピクセルデータがまだ揃っていないので0にする
lap_fb[y*HORIZONTAL_PIXEL_WIDTH+x] = 0;
// printf("x = %d y = %d", x, y);
}
}
return(0);
}
// RGBからYへの変換
// RGBのフォーマットは、{8'd0, R(8bits), G(8bits), B(8bits)}, 1pixel = 32bits
// 輝度信号Yのみに変換する。変換式は、Y = 0.299R + 0.587G + 0.114B
// "YUVフォーマット及び YUV<->RGB変換"を参考にした。http://vision.kuee.kyoto-u.ac.jp/~hiroaki/firewire/yuv.html
// 2013/09/27 : float を止めて、すべてint にした
int conv_rgb2y(int rgb){
int r, g, b, y_f;
int y;
b = rgb & 0xff;
g = (rgb>>8) & 0xff;
r = (rgb>>16) & 0xff;
y_f = 77*r + 150*g + 29*b; //y_f = 0.299*r + 0.587*g + 0.114*b;の係数に256倍した
y = y_f >> 8; // 256で割る
return(y);
}
を定義して、for 文の中を以下の通りに書き換えても同様の動作となった。int colbuf[3];
#pragma HLS ARRAY_PARTITION variable=colbuf complete dim=1
for (y=0; y<VERTICAL_PIXEL_WIDTH; y++){
for (x=0; x<HORIZONTAL_PIXEL_WIDTH; x++){
// 1ピクセル読み出し
pix = cam_fb[y*HORIZONTAL_PIXEL_WIDTH+x];
// colbuf[] にラインバッファと読みだしたピクセルを入れる
colbuf[2] = linebuf(1,x);
colbuf[1] = linebuf(0,x);
colbuf[0] = pix;
mbuf.shift_left(); // mbuf の列を1ビット左シフト
mbuf.insert_left(colbuf); // mbuf の列に colbuf[] を代入
// LineBuffer の更新
linebuf.shift_down(x);
linebuf.insert_bottom(pix, x);
// ラプラシアンフィルタの演算
for (j=0, val=0; j<3; j++){
for (i=0; i<3; i++){
t_val = mbuf(2-j,i);
val += lap_weight[j][i] * conv_rgb2y(t_val);
}
}
if (val<0) // 飽和演算
val = 0;
else if (val>255)
val = 255;
// ラプラシアンフィルタ・データの書き込み
if (x>1 && y>1)
lap_fb[y*HORIZONTAL_PIXEL_WIDTH+x] = (val<<16)+(val<<8)+val ;
else
// x<2 || y<2 の場合はピクセルデータがまだ揃っていないので0にする
lap_fb[y*HORIZONTAL_PIXEL_WIDTH+x] = 0;
// printf("x = %d y = %d", x, y);
}
}
libdc1394 error: Failed to initialize libdc1394
...0 pairs have been successfully detected.
Error: too little pairs to run the calibration
// display_enable 出力
always @(posedge clk_disp) begin
if (reset_disp)
display_enable <= 1'b1;
else begin
if (h_count<H_ACTIVE_VIDEO && v_count<V_ACTIVE_VIDEO)
display_enable <= 1'b1;
else
display_enable <= 1'b0;
end
end
// display_enable 出力
always @(posedge clk_disp) begin
if (reset_disp==1'b1 || cs_rdg==idle_rdg || cs_rdg==init_full_mode)
de <= 1'b0;
else begin
if (h_count<H_ACTIVE_VIDEO && v_count<V_ACTIVE_VIDEO)
de <= 1'b1;
else
de <= 1'b0;
end
end
always @(posedge clk_disp) begin
if(reset_disp==1'b1 || cs_rdg==idle_rdg || cs_rdg==init_full_mode) begin
de_b1 <= 1'b0;
end begin
de_b1 <= de;
end
end
assign display_enable = de_b1;
日 | 月 | 火 | 水 | 木 | 金 | 土 |
---|---|---|---|---|---|---|
- | - | 1 | 2 | 3 | 4 | 5 |
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 | 31 | - | - |