void image_filter(AXI_STREAM& INPUT_STREAM, AXI_STREAM& OUTPUT_STREAM, int rows, int cols) {
//Create AXI streaming interfaces for the core
#pragma HLS RESOURCE variable=INPUT_STREAM core=AXIS metadata="-bus_bundle INPUT_STREAM"
#pragma HLS RESOURCE variable=OUTPUT_STREAM core=AXIS metadata="-bus_bundle OUTPUT_STREAM"
#pragma HLS RESOURCE core=AXI_SLAVE variable=rows metadata="-bus_bundle CONTROL_BUS"
#pragma HLS RESOURCE core=AXI_SLAVE variable=cols metadata="-bus_bundle CONTROL_BUS"
#pragma HLS RESOURCE core=AXI_SLAVE variable=return metadata="-bus_bundle CONTROL_BUS"
#pragma HLS INTERFACE ap_stable port=rows
#pragma HLS INTERFACE ap_stable port=cols
RGB_IMAGE img_0(rows, cols);
RGB_IMAGE img_1(rows, cols);
#pragma HLS dataflow
hls::AXIvideo2Mat(INPUT_STREAM, img_0);
RGB_PIXEL buffer[3];
assert(rows <= MAX_HEIGHT);
assert(cols <= MAX_WIDTH);
for(int row = 0; row < rows; row++) {
#pragma HLS loop_flatten off
for(int col = 0; col < cols; col++) {
#pragma HLS pipeline II=1
RGB_PIXEL p;
img_0 >> p;
buffer[2] = buffer[1];
buffer[1] = buffer[0];
buffer[0] = p;
// Because we have a buffer above, the start of one line
// will be processed with data from the previous line.
// The check below is a simple, relatively unsophisticated
// way to handle the edge condition. It does result in
// introducing a spatial shift in the image because the
// filter is non-causal.
if(col > 1) {
for(int i = 0; i < 3; i++) {
bool a = buffer[2].val[i] > buffer[1].val[i];
bool b = buffer[2].val[i] > buffer[0].val[i];
bool c = buffer[1].val[i] > buffer[0].val[i];
if(a && c) {
p.val[i] = buffer[1].val[i];
} else if(b && !c) {
p.val[i] = buffer[0].val[i];
} else {
p.val[i] = buffer[2].val[i];
}
}
}
img_1 << p;
}
}
hls::Mat2AXIvideo(img_1, OUTPUT_STREAM);
}
|