1. 程式人生 > >caffe資料層相關學習以及訓練線上資料增廣

caffe資料層相關學習以及訓練線上資料增廣

caffe資料層是將已經生成好的LMDB檔案中的label和資料讀入到Datum資料結構體中,然後將資料轉化到Blob中,進而進行資料傳遞,才能進行資料訓練。目前使用的data_layer是經過了別人的改版,能夠讀入多個LMDB,並且在source_filelists中除了寫入影象資料,還會加入每個資料樣本所對應的key,從而實現Key—Value一一對應的結果。

本次希望實現的主要功能是希望在訓練過程中,能夠實時的隨機改變影象資料的飽和度、亮度和對比度,進而能夠達到資料增廣的目的,增加資料的多樣性,使得訓練得到的模型的泛化性更好。而如果要達到這樣的目的,就需要對data_transformer.cpp進行相應的程式碼更改。除此以外,因為希望在訓練過程中,只對負樣本進行資料增廣,而不改變正樣本。所以還需要對data_layer層進行相應更改。因為最初生成的key中已經記錄了樣本的正負屬性,所以可以在對key進行相應處理知道屬性是“正”or“負”。

提前在資料結構體中增加了bool is_augmentated變數。如果在data_layer中判斷樣本為負,則將is_augmentated值設為true,則在data_transformer.cpp中進行相應的資料增廣。

在data_transformer.cpp和data_transformer.hpp中首先新增調整影象飽和度、亮度和對比度的函式。幾個函式都傳入的是Blob資料體的資料頭,因為已經Blob的地址都是連續的,這樣方便直接進行地址操作。但是要注意,和cv::Mat的資料儲存格式HWC有所區別,Blob的儲存格式是CHW,因此在使用指標進行地址操作的時候,需要進行相應的轉變。

飽和度調整函式程式碼如下:

template <typename Dtype> \\注意次數需要使用對應的模板
	void DataTransformer<Dtype>::Saturation( \\飽和度調整
		Dtype* img, \\ 第一個坑,儘管blob是float型的,但是因為使用了模板,所以需要將所有和blob掛鉤的變數型別都要更改為Dtype,這是一個模板型別的變數。
		const int img_size,
		const float alpha_rand  \\ 增廣引數的範圍,該引數是在網路中設定的,所以需要相應的更改caffe.proto檔案,在TransformationParameter中增加相關引數	) {
		float alpha = 0.0f;
		Dtype tempPixel = 0.0f;
		GenerateRandomFloat_range(alpha_rand, &alpha); \\根據caffe自帶的隨機數生成器Rand(),得到-alpha_rand~alpha_rand的隨機實數
		// BGR to Gray scale image: R -> 0.299, G -> 0.587, B -> 0.114
		for (int h = 0; h < img_size; ++h) {
			for (int w = 0; w < img_size; ++w) {
				Dtype gray_color = img[0 * img_size*img_size + h*img_size + w] * 0.114f + img[1 * img_size*img_size + h*img_size + w] * 0.587f +
					img[2 * img_size*img_size + h*img_size + w] * 0.299f; 
                 // 因為是已經是直接對Blob進行地址操作,所以可以直接使用指標頭進行相應的位置移
                for (int c = 0; c < 3; ++c) { t
                        empPixel = img[c * img_size*img_size + h*img_size + w] * alpha + gray_color * (1.0f - alpha);img[c * img_size*img_size + h*img_size + w] = CheckAugmentatedValue(&tempPixel); 
                 //CheckAugmentatedValue()是特意增加的邊界檢測,防止修改後的數值超過[0,255]的影象範圍
				}
			}
		}
	}
調整亮度和對比度的程式碼和飽和度的類似,不再增加相關注釋
// assume HWC order and color channels BGR
	template <typename Dtype>
	void DataTransformer<Dtype>::Brightness(
		Dtype* img,
		const int img_size,
		const float alpha_rand
		) {
		float alpha = 0.0f;
		Dtype tempPixel = 0.0f;
		GenerateRandomFloat_range(alpha_rand, &alpha);
		LOG(INFO) << "Brightness Alpha = " << alpha;
		int p = 0;
		for (int h = 0; h < img_size; ++h) {
			for (int w = 0; w < img_size; ++w) {
				for (int c = 0; c < 3; ++c) {
					tempPixel = img[p] * alpha;
					img[p] = CheckAugmentatedValue(&tempPixel);
					p++;
				}
			}
		}
	}
template <typename Dtype>
	void DataTransformer<Dtype>::Contrast(
		Dtype* img,
		const int img_size,
		const float alpha_rand
		) {
		float gray_mean = 0;
		Dtype tempPixel = 0;
		for (int h = 0; h < img_size; ++h) {
			for (int w = 0; w < img_size; ++w) {
				// BGR to Gray scale image: R -> 0.299, G -> 0.587, B -> 0.114
				gray_mean += img[0 * img_size*img_size + h*img_size + w] * 0.114f + img[1 * img_size*img_size + h*img_size + w] * 0.587f +
					img[2 * img_size*img_size + h*img_size + w] * 0.299f;
			}
		}
		gray_mean /= (img_size * img_size);

		float alpha = 0.0f;
		GenerateRandomFloat_range(alpha_rand, &alpha);
		LOG(INFO) << "Contrast Alpha = " << alpha;
		int p = 0;
		for (int h = 0; h < img_size; ++h) {
			for (int w = 0; w < img_size; ++w) {
				for (int c = 0; c < 3; ++c) {
					tempPixel = img[p] * alpha + gray_mean * (1.0f - alpha);
					img[p] = CheckAugmentatedValue(&tempPixel);
					p++;
				}
			}
		}
	}