//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的博客
评论
查看更多