代码是使用opencv写的,实现起来也非常简单。一共传入3个参数,分别是原图,池化的size,最后一个是步长。
Mat pooling(Mat img, int grid, int overlap)
{
Mat pool_img = Mat((int)((img.rows - 1) / overlap) + 1, (int)((img.cols - 1) / overlap)+1, CV_8UC1);
for (int col = 0,pool_col=0; col < img.cols; col+= overlap)
{
for (int row = 0,pool_row=0; row < img.rows; row+= overlap)
{
int minCol = min(col + overlap, img.cols);
int maxData = 0;
for (int poolX = col; poolX < minCol; poolX++)
{
int minRow = min(row + overlap, img.rows);
for (int poolY = row; poolY<minRow; poolY++)
{
if (img.at<uchar>(poolY, poolX)>maxData)
{
maxData = img.at<uchar>(poolY, poolX);
}
}
}
pool_img.at<uchar>(pool_row, pool_col) = maxData;
pool_row++;
}
pool_col++;
}
return pool_img;
}
所谓的池化目的就是抽象,把一大片面积总结成一个数,比方说一副100*100的图,我们每50*50的区域就取一个最大值,共计能取4个最大值,那么这个2*2的最大值图像就是池化后的图像了
上图是一个20*20的图经过size为10步长也为10的池化,最后生成了一个2*2的图。其实最后生成的图与池化的size并没有什么直接关系,真正影响他的是池化的步长,也就是说这一操作不仅可以像上图那样紧挨着移动,还可以隔着几格移动,例如步长如果是11那么就是隔着一格移动了。当然也可以重叠的移动,例如步长是5那么每两个中间就重叠了五格。至于最后如果有出界的情况怎么办。我采取的办法是把出界的部分延长,当0来考虑,反正是求最大值,相当于就没有考虑他们。
这样的话池化结果的大小应该就是原图的大小/步长,如果是小数并且按我的延长方法处理的话就进一,如果选择舍弃的话就取整。