pooling池化操作的代碼詳解

池化這個操作原理非常簡單,相信大家都很容易搞懂,那麼這篇博客就主要從代碼來談談吧。

首先還是簡單介紹一下原理(不是我偷懶想要簡單介紹,是因爲這個東西介紹起來本身就很簡單偷笑

所謂的池化目的就是抽象,把一大片面積總結成一個數,比方說一副100*100的圖,我們每50*50的區域就取一個最大值,共計能取4個最大值,那麼這個2*2的最大值圖像就是池化後的圖像了。

上圖是一個20*20的圖經過size爲10步長也爲10的池化,最後生成了一個2*2的圖。其實最後生成的圖與池化的size並沒有什麼直接關係,真正影響他的是池化的步長,也就是說這一操作不僅可以像上圖那樣緊挨着移動,還可以隔着幾格移動,例如步長如果是11那麼就是隔着一格移動了。當然也可以重疊的移動,例如步長是5那麼每兩個中間就重疊了五格。至於最後如果有出界的情況怎麼辦。我採取的辦法是把出界的部分延長,當0來考慮,反正是求最大值,相當於就沒有考慮他們。

這樣的話池化結果的大小應該就是原圖的大小/步長,如果是小數並且按我的延長方法處理的話就進一,如果選擇捨棄的話就取整。

附上代碼:

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;
}
代碼是使用opencv寫的,實現起來也非常簡單。一共傳入3個參數,分別是原圖,池化的size,最後一個是步長。

可以看到

Mat pool_img = Mat((int)((img.rows - 1) / overlap) + 1, (int)((img.cols - 1) / overlap)+1, CV_8UC1);

這一句就是按之前說的方法定義池化後的圖像,大小就是用的原圖大小/步長然後進一。爲什麼我要先-1呢,這是因爲如果不-1那麼後面進一操作在剛好能整除的時候就多了1了。就像圖中的例子,20/10=2,剛好能整除,如果直接+1就會多出來一格,所以先-1再除再加上1能很好的應對這個問題。

接着就是按照步長遍歷原圖,每一個區域都尋找最大值,然後賦值給新的結果。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章