Canny Edge Detectionのアルゴリズムは次の手順。
STEP1:ガウシアンフィルタで平滑化
STEP2:エッジ強度と勾配方向(4方向に量子化)を計算
STEP3:細線化処理(Non-maximum Suppression)
STEP4:ヒステリシス閾処理(Hysteresis Threshold)
void lap_filter(AXI_STREAM& input, AXI_STREAM& output, int rows, int cols, int threshold_low, int threshold_high) {
#pragma HLS INTERFACE s_axilite port=return
#pragma HLS DATAFLOW
#pragma HLS INTERFACE s_axilite port=threshold_high
#pragma HLS INTERFACE s_axilite port=threshold_low
#pragma HLS INTERFACE s_axilite port=cols
#pragma HLS INTERFACE s_axilite port=rows
#pragma HLS INTERFACE axis port=output
#pragma HLS INTERFACE axis port=input
#pragma HLS INTERFACE ap_stable port=rows
#pragma HLS INTERFACE ap_stable port=cols
RGB_IMAGE src(rows, cols);
RGBSINGLE_IMAGE src_bw(rows, cols);
RGBSINGLE_IMAGE src_blur(rows, cols);
RGBSINGLE_IMAGE lap_fil(rows, cols);
RGB_IMAGE lap_fil_color(rows, cols);
RGB_IMAGE lap_edges(rows, cols);
//#pragma HLS dataflow
// AXI to RGB_IMAGE stream
hls::AXIvideo2Mat( input, src );
// Grayscaling
hls::CvtColor<HLS_RGB2GRAY>( src, src_bw );
// Gaussian Blur Noise Reduction
hls::GaussianBlur<5,5>( src_bw, src_blur );
//hls::GaussianBlur<3,3>( src_bw, src_blur);
// Calculate laplacian filter
const int lap_weight[3][3] = {{-1, -1, -1},{-1, 8, -1},{-1, -1, -1}};
hls::Window<3, 3, int> kernel;
hls::Point_<int> anchor;
for (int i=0; i<3; i++){
for (int j=0; j<3; j++){
kernel.val[i][j] = lap_weight[i][j];
}
}
anchor.x = -1;
anchor.y = -1;
hls::Filter2D(src_blur, lap_fil, kernel, anchor);
// gray to color
hls::CvtColor<HLS_GRAY2BGR>( lap_fil, lap_fil_color );
// Perform hysteresis thresholding for edge tracing
hysteresis( lap_fil_color, lap_edges, threshold_low, threshold_high );
hls::Mat2AXIvideo(lap_edges, output );
}
// Lane-Detecting_tb.cpp
// 2016/05/22 by marsee
// OpenCV 2 の Mat を使用したバージョン
// Vivado HLSでは Canny フィルタのみハードウェア化した。OpenCV で処理したCannyフィルタとHough変換を行って比較する。
#include <iostream>
#include "hls_opencv.h"
#include "lap_filter.h"
using namespace cv;
void lap_filter(AXI_STREAM& input, AXI_STREAM& output, int rows, int cols, int threshold_low, int threshold_high);
void opencv_lap_filter(Mat& src, Mat& dst, int threshold_low, int threshold_high, int sobel_size);
int main (int argc, char** argv) {
//const int threshold_low = 50;
//const int threshold_high = 200;
const int threshold_low = 40;
const int threshold_high = 50;
const int sobel_size = 3;
// OpenCV で 画像を読み込む
Mat src = imread(INPUT_IMAGE);
AXI_STREAM src_axi, dst_axi;
// Mat フォーマットから AXI4 Stream へ変換
cvMat2AXIvideo(src, src_axi);
// image_filter() 関数をコール
lap_filter(src_axi, dst_axi, src.rows, src.cols, threshold_low, threshold_high);
// AXI4 Stream から Mat フォーマットへ変換
// dst は宣言時にサイズとカラー・フォーマットを定義する必要がある
Mat dst(src.rows, src.cols, CV_8UC3);
AXIvideo2cvMat(dst_axi, dst);
imshow("Vivado HLS lap_filter", dst);
// opencv_image_filter() をコール
Mat dst_cv(src.rows, src.cols, CV_8UC3);
opencv_lap_filter(src, dst_cv, 200, 300, sobel_size);
imshow("OpenCV Canny filter", dst_cv);
// Vivado HLS の Canny filter の Hough変換
// detect lines
vector<Vec2f> lines;
Mat gray_dst;
cvtColor(dst, gray_dst, CV_BGR2GRAY);
HoughLines(gray_dst, lines, 1, CV_PI/180, 120, 0, 0);
// draw lines
for( size_t i = 0; i < lines.size(); i++ )
{
float rho = lines[i][0], theta = lines[i][1];
Point pt1, pt2;
double a = cos(theta), b = sin(theta);
double x0 = a*rho, y0 = b*rho;
pt1.x = cvRound(x0 + 1000*(-b));
pt1.y = cvRound(y0 + 1000*(a));
pt2.x = cvRound(x0 - 1000*(-b));
pt2.y = cvRound(y0 - 1000*(a));
line( dst, pt1, pt2, Scalar(0,0,255), 3, CV_AA);
}
imwrite(OUTPUT_IMAGE, dst);
// OpenCV の Canny filter の Hough変換
// detect lines
Mat cdst_cv;
cvtColor(dst_cv, cdst_cv, CV_GRAY2BGR);
HoughLines(dst_cv, lines, 1, CV_PI/180, 150, 0, 0);
// draw lines
for( size_t i = 0; i < lines.size(); i++ )
{
float rho = lines[i][0], theta = lines[i][1];
Point pt1, pt2;
double a = cos(theta), b = sin(theta);
double x0 = a*rho, y0 = b*rho;
pt1.x = cvRound(x0 + 1000*(-b));
pt1.y = cvRound(y0 + 1000*(a));
pt2.x = cvRound(x0 - 1000*(-b));
pt2.y = cvRound(y0 - 1000*(a));
line( cdst_cv, pt1, pt2, Scalar(0,0,255), 3, CV_AA);
}
imwrite(OUTPUT_IMAGE_GOLDEN, cdst_cv);
printf("Test with 0 errors.\n");
imshow("Detect lines of Vivado HLS lap_filter", dst);
imshow("Detect lines of OpenCV", cdst_cv);
waitKey();
return 0;
}
void opencv_lap_filter(Mat& src, Mat& dst, int threshold_low, int threshold_high, int sobel_size){
Canny(src, dst, (double)threshold_low, (double)threshold_high, sobel_size);
}
日 | 月 | 火 | 水 | 木 | 金 | 土 |
---|---|---|---|---|---|---|
- | - | - | - | - | 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 | - | - | - | - | - | - |