I am trying to implement a connected component labelling algorithm in Vivado HLS. Here is the link to the algorithm I am using: two pass connected component labelling algorithm.
I am using a 3x3 window in Vivado HLS and send that window to my connected object algorithm function. This function returns a single pixel according to algorithm and stores it to a destination image and appends successive pixel as they come. But, while processing next window, it ignores the result of the previous operation, while the algorithm requires it to compare with previous output pixel.
I need to find a way to consider that pixel or make changes in destination image itself.
Here is my code:
conn.cpp
#include "CONN.h"
int label=50;
int min;
MY_PIXEL find_conn(MY_WINDOW *window)
{
unsigned char west, north, northWest, northEast, south, east, southEast, southWest=0;
MY_PIXEL pixel;
char i=0;
char j=0;
// pixel.val[0]=window->getval(i,j); //to make copy of original image.
west=window->getval(i+1,j);
northWest=window->getval(i,j);
north=window->getval(i,j+1);
northEast=window->getval(i,j+2);
if(window->getval(i+1,j+1)!=0){
min=9600;
if(west!=0||north!=0||northWest!=0||northEast!=0){
if(west<min && west!=0) min=west;
if(northWest<min && north!=0) min=northWest;
if(north<min && north!=0) min=north;
if(northEast!=0 && northEast!=0) min=northEast;
window->insert(min,i+1,j+1);
}
else
{
label= label+10;
window->insert(label,i+1,j+1);
}
}
pixel.val[0]=window->getval(i+1,j+1);
return pixel;
}
void created_window(MY_IMAGE& src, MY_IMAGE& dst, int rows, int cols)
{
MY_BUFFER buff_A;
MY_WINDOW WINDOW_3x3;
for(int row = 0; row < rows+1; row++){
for(int col = 0; col < cols+1; col++){
#pragma HLS loop_flatten off
#pragma HLS dependence variable=&buff_A false
#pragma HLS PIPELINE II = 1
// Temp values are used to reduce the number of memory reads
unsigned char temp;
MY_PIXEL tempx;
//Line Buffer fill
if(col < cols){
buff_A.shift_down(col);
temp = buff_A.getval(0,col);
}
//There is an offset to accommodate the active pixel region
//There are only MAX_WIDTH and MAX_HEIGHT valid pixels in the image
if(col < cols && row < rows){
MY_PIXEL new_pix;
src >> new_pix;
tempx = new_pix;
buff_A.insert_bottom(tempx.val[0],col);
}
//Shift the processing window to make room for the new column
WINDOW_3x3.shift_right();
//The processing window only needs to store luminance values
//rgb2y function computes the luminance from the color pixel
if(col < cols){
WINDOW_3x3.insert(buff_A.getval(2,col),2,0);
WINDOW_3x3.insert(temp,1,0);
WINDOW_3x3.insert(tempx.val[0],0,0);
}
MY_PIXEL conn_obj;
//The operator only works on the inner part of the image
//This design assumes there are no connected objects on the boundary of the image
conn_obj = find_conn(&WINDOW_3x3);
//The output image is offset from the input to account for the line buffer
if(row > 0 && col > 0) {
dst << conn_obj;
}
}
}
}
void create_window(AXI_STREAM& video_in, AXI_STREAM& video_out, int rows, int cols)
{
//Create AXI streaming interfaces for the core
#pragma HLS INTERFACE axis port=video_in bundle=INPUT_STREAM
#pragma HLS INTERFACE axis port=video_out bundle=OUTPUT_STREAM
#pragma HLS INTERFACE s_axilite port=rows bundle=CONTROL_BUS offset=0x14
#pragma HLS INTERFACE s_axilite port=cols bundle=CONTROL_BUS offset=0x1C
#pragma HLS INTERFACE s_axilite port=return bundle=CONTROL_BUS
#pragma HLS INTERFACE ap_stable port=rows
#pragma HLS INTERFACE ap_stable port=cols
MY_IMAGE img_0(rows, cols);
MY_IMAGE img_1(rows, cols);
#pragma HLS dataflow
hls::AXIvideo2Mat(video_in, img_0);
created_window(img_0, img_1, rows, cols);
hls::Mat2AXIvideo(img_0, video_out);
}
conn.h
#ifndef _TOP_H_
#define _TOP_H_
#include "hls_video.h"
#define MAX_WIDTH 320
#define MAX_HEIGHT 240
typedef hls::stream<ap_axiu<8,1,1,1> > AXI_STREAM;
typedef hls::Scalar<1, unsigned char> MY_PIXEL;
typedef hls::Mat<MAX_HEIGHT, MAX_WIDTH, HLS_8UC1> MY_IMAGE;
typedef hls::Window<3, 3, unsigned char> MY_WINDOW;
typedef hls::LineBuffer<3, MAX_WIDTH, unsigned char> MY_BUFFER;
void create_window(AXI_STREAM& INPUT_STREAM, AXI_STREAM& OUTPUT_STREAM, int rows, int cols);
#endif
As requested here is my main.c
#include "CONN.h"
#include <hls_video.h>
#include <hls_opencv.h>
#define INPUT_FILE "D:/TRACKING PRADNAYA/test_image/test_conn.jpg"
#define OUTPUT_FILE "D:/TRACKING PRADNAYA/test_image/test_conn_out.jpg"
int main(){
cv::Mat inputMat(MAX_HEIGHT, MAX_WIDTH, CV_8UC1);
cv::Mat outputMat(MAX_HEIGHT, MAX_WIDTH, CV_8UC1);
inputMat = cv::imread(INPUT_FILE, CV_LOAD_IMAGE_GRAYSCALE);
AXI_STREAM inStream_1;
AXI_STREAM outStream_conn;
cvMat2AXIvideo(inputMat, inStream_1);
create_window(inStream_1, outStream_conn, inputMat.rows, inputMat.cols);
AXIvideo2cvMat(outStream_conn, outputMat);
cv::imwrite(OUTPUT_FILE, outputMat );
return 0;
}