//Line Buffer fill
if(col < cols){
buff_A.shift_down(col);
//行存shift
temp = buff_A.getval(0,col);
//這里的行存里的row = 0 和row = 1 的值是相同的
}
//There is an offset to accomodate the active pixel region
//There are only MAX_WIDTH and MAX_HEIGHT valid pixels in the image
if(col < cols && row < rows){
YUV_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
buff_C.shift_right();
//窗右移空出一列
//The Sobel processing window only needs to store luminance values
//rgb2y function computes the luminance from the color pixel
if(col < cols){
//將數據從行存里復制到窗中,
//對于這里為什么將之前的 temp = buff_A.getval(0,col)
//而不是直接復制行存中row=1的數據,就如同對行存中row=2的數據的操作
//eg: buff_C.insert(buff_A.getval(2,col),2,0);
//
buff_C.insert(buff_A.getval(1,col),1,0);
//
buff_C.insert(tempx.val[0],0,0);
//有疑問,猜想可能是Synthesis的時候并行化有影響
buff_C.insert(buff_A.getval(2,col),2,0);
buff_C.insert(temp,1,0);
buff_C.insert(tempx.val[0],0,0);
}
YUV_PIXEL edge;
//如下是基本的sobel算法的流程了 注意圖像邊緣的位置排除
//The sobel operator only works on the inner part of the image
//This design assumes there are no edges on the boundary of the image
if( row <= 1 || col <= 1 || row > (rows-1) || col > (cols-1)){
edge.val[0] = 0;
edge.val[1] = 128;
} else {
//Sobel operation on the inner portion of the image
edge = sobel_operator(&buff_C,
C_XR0C0, C_XR0C1, C_XR0C2, C_XR1C0, C_XR1C1, C_XR1C2, C_XR2C0, C_XR2C1, C_XR2C2,
C_YR0C0, C_YR0C1, C_YR0C2, C_YR1C0, C_YR1C1, C_YR1C2, C_YR2C0, C_YR2C1, C_XR2C2,
c_high_thresh, c_low_thresh, c_invert);
}
//The output image is offset from the input to account for the line buffer
if(row > 0 && col > 0) {
dst << edge;
}
}
}
}
參照ug902文檔
hls::LineBuffer
The main features of the LineBuffer class are:
? Support for all data types through parameterization
? User-defined number of rows and columns
? Automatic banking of rows into separate memory banks for increased memory
bandwidth
? Provides all the methods for using and debugging line buffers in an algorithmic design
hls::Window
? Support for all data types through parametrization
? User-defined number of rows and columns
? Automatic partitioning into individual registers for maximum bandwidth
? Provides all the methods to use and debug memory windows in the context of an
algorithm
由于采用的是stearm流的形式處理圖像數據,所以并不能訪問圖像上任意一點的值,為了方便濾波模板的操作提供了這兩種數據結構,這里的sobel算子要求有一個3*3大小的窗與模板相乘,要產生這樣的窗則需要一個三行數據的行存,兩層的row、col循環中每次都把行存中col列的數據shift_down操作然后將新得到的數據插入到底部,注意這里和ug902的文檔有出入,查看源碼,發現ug902的文檔上是錯的 源碼中定義的 top和bottom方向如下
/* Member functions of LineBuffer class */
/*
+---+---+-... ...-+---+---+
* R-1 | | |
| | |
*
+---+---+-... ...-+---+---+
* R-2 | | |
| | |
*
+---+---+-... ...-+---+---+
*
...
... ... ...
*
+---+---+-... ...-+---+---+
* 1 | | |
| | |
*
+---+---+-... ...-+---+---+
* 0 | | |
| | |
*
+---+---+-... ...-+---+---+
*
0 1 ... ... C-2 C-1 (origin is at bottom-left point)
*/
可能是官方的文檔(v2014.1)沒有更新
sobel_operator
x、y方向模板與窗相乘 沒啥可說的了
YUV_PIXEL sobel_operator(Y_WINDOW *window,
int XR0C0, int XR0C1, int XR0C2, int XR1C0, int XR1C1, int XR1C2, int XR2C0, int XR2C1, int XR2C2,
int YR0C0, int YR0C1, int YR0C2, int YR1C0, int YR1C1, int YR1C2, int YR2C0, int YR2C1, int YR2C2,
int high_thesh, int low_thresh, int invert)
{
short x_weight = 0;
short y_weight = 0;
short edge_weight;
unsigned char edge_val;
YUV_PIXEL pixel;
char i;
char j;
const char x_op[3][3] = {{XR0C0,XR0C1,XR0C2},
{XR1C0,XR1C1,XR1C2},
{XR2C0,XR2C1,XR2C2}};
const char y_op[3][3] = {{YR0C0,YR0C1,YR0C2},
{YR1C0,YR1C1,YR1C2},
{YR2C0,YR2C1,YR2C2}};
//Compute approximation of the gradients in the X-Y direction
for(i=0; i < 3; i++){
for(j = 0; j < 3; j++){
// X direction gradient
x_weight = x_weight + (window->getval(i,j) * x_op[i][j]);
// Y direction gradient
y_weight = y_weight + (window->getval(i,j) * y_op[i][j]);
}
}
edge_weight = ABS(x_weight) + ABS(y_weight);
if (edge_weight < 255)
edge_val = (255-(unsigned char)(edge_weight));
else
edge_val = 0;
//Edge thresholding
if(edge_val > high_thesh)
edge_val = 255;
else if(edge_val < low_thresh)
edge_val = 0;
// Invert
if (invert == 1)
edge_val = 255 - edge_val;
pixel.val[0] = edge_val;
pixel.val[1] = 128;
return pixel;
}
文章轉載自:Thssasuke的博客
評論
查看更多