C++实现:批量对图片进行水平镜像、切片、旋转、添加椒盐噪声。
应用场景:小样本学习中图像扩充。
#include <iostream> #include <string> #include <fstream> #include <opencv2/opencv.hpp> using namespace cv; using namespace std; Mat addSaltNoise(const Mat srcImage, int n); Mat rotateImage(Mat img, int degree); void main() { int i = 0; string name, clas; ifstream infile; infile.open("F:/小样本学习图片数据/xifang/org_img/train.txt"); string image_dir = "F:/小样本学习图片数据/xifang/org_img/train/"; while (infile) { infile >> name >> clas; cout << i++ << endl; string image_dir_name = image_dir + name; Mat image = imread(image_dir_name, -1); // 1、对图像进行水平镜像 string image_jingxiang = "F:/小样本学习图片数据/xifang/生成后的train图片/水平镜像/"; string image_out_jingxiang = image_jingxiang + name; Mat img_jingxiang; img_jingxiang.create(image.size(), image.type()); for (int i = 0; i < image.rows; i++) { for (int j = 0; j < image.cols; j++) { img_jingxiang.at<Vec3b>(i, j)[0] = image.at<Vec3b>(i, image.cols - 1 - j)[0]; img_jingxiang.at<Vec3b>(i, j)[1] = image.at<Vec3b>(i, image.cols - 1 - j)[1]; img_jingxiang.at<Vec3b>(i, j)[2] = image.at<Vec3b>(i, image.cols - 1 - j)[2]; } } imwrite(image_out_jingxiang, img_jingxiang); // 2、对图像进行切片,右上角切片 string image_qiepian_youshang = "F:/小样本学习图片数据/xifang/生成后的train图片/切片/右上角切片/"; string image_out_qiepian_youshang = image_qiepian_youshang + name; //Rect bbox(0, 0, 224, 224); // 左上角切片 Rect bbox1(image.cols - 1 - 224, 0, 224, 224); // 右上角切片 //Rect bbox(0, image.rows - 1 - 224, 224, 224); // 左下角切片 //Rect bbox(image.cols - 1 - 224, image.rows - 1 - 224, 224, 224); // 右下角切片 //Rect bbox(image.cols/2- 112, image.rows/2 -112,224, 224); // 中间切片 Mat img_qiepian_youshang = image(bbox1); cv::resize(img_qiepian_youshang, img_qiepian_youshang, cv::Size(256, 256), cv::INTER_LINEAR); imwrite(image_out_qiepian_youshang, img_qiepian_youshang); // 3、对图像进行切片,右下角切片 string image_qiepian_youxia = "F:/小样本学习图片数据/xifang/生成后的train图片/切片/右下角切片/"; string image_out_qiepian_youxia = image_qiepian_youxia + name; //Rect bbox(0, 0, 224, 224); // 左上角切片 //Rect bbox(image.cols - 1 - 224, 0, 224, 224); // 右上角切片 //Rect bbox(0, image.rows - 1 - 224, 224, 224); // 左下角切片 Rect bbox2(image.cols - 1 - 224, image.rows - 1 - 224, 224, 224); // 右下角切片 //Rect bbox(image.cols/2- 112, image.rows/2 -112,224, 224); // 中间切片 Mat img_qiepian_youxia = image(bbox2); cv::resize(img_qiepian_youxia, img_qiepian_youxia, cv::Size(256, 256), cv::INTER_LINEAR); imwrite(image_out_qiepian_youxia, img_qiepian_youxia); // 4、对图像进行切片,中间切片 string image_qiepian_zhongjian = "F:/小样本学习图片数据/xifang/生成后的train图片/切片/中间切片/"; string image_out_qiepian_zhongjian = image_qiepian_zhongjian + name; //Rect bbox(0, 0, 224, 224); // 左上角切片 //Rect bbox(image.cols - 1 - 224, 0, 224, 224); // 右上角切片 //Rect bbox(0, image.rows - 1 - 224, 224, 224); // 左下角切片 //Rect bbox(image.cols - 1 - 224, image.rows - 1 - 224, 224, 224); // 右下角切片 Rect bbox3(image.cols/2- 112, image.rows/2 -112,224, 224); // 中间切片 Mat img_qiepian_zhongjian = image(bbox3); cv::resize(img_qiepian_zhongjian, img_qiepian_zhongjian, cv::Size(256, 256), cv::INTER_LINEAR); imwrite(image_out_qiepian_zhongjian, img_qiepian_zhongjian); // 5、对图像进行切片,左上角切片 string image_qiepian_zuoshang = "F:/小样本学习图片数据/xifang/生成后的train图片/切片/左上角切片/"; string image_out_qiepian_zuoshang = image_qiepian_zuoshang + name; Rect bbox4(0, 0, 224, 224); // 左上角切片 //Rect bbox(image.cols - 1 - 224, 0, 224, 224); // 右上角切片 //Rect bbox(0, image.rows - 1 - 224, 224, 224); // 左下角切片 //Rect bbox(image.cols - 1 - 224, image.rows - 1 - 224, 224, 224); // 右下角切片 //Rect bbox(image.cols / 2 - 112, image.rows / 2 - 112, 224, 224); // 中间切片 Mat img_qiepian_zuoshang = image(bbox4); cv::resize(img_qiepian_zuoshang, img_qiepian_zuoshang, cv::Size(256, 256), cv::INTER_LINEAR); imwrite(image_out_qiepian_zuoshang, img_qiepian_zuoshang); // 6、对图像进行切片,左下角切片 string image_qiepian_zuoxia = "F:/小样本学习图片数据/xifang/生成后的train图片/切片/左下角切片/"; string image_out_qiepian_zuoxia = image_qiepian_zuoxia + name; //Rect bbox4(0, 0, 224, 224); // 左上角切片 //Rect bbox(image.cols - 1 - 224, 0, 224, 224); // 右上角切片 Rect bbox5(0, image.rows - 1 - 224, 224, 224); // 左下角切片 //Rect bbox(image.cols - 1 - 224, image.rows - 1 - 224, 224, 224); // 右下角切片 //Rect bbox(image.cols / 2 - 112, image.rows / 2 - 112, 224, 224); // 中间切片 Mat img_qiepian_zuoxia = image(bbox5); cv::resize(img_qiepian_zuoxia, img_qiepian_zuoxia, cv::Size(256, 256), cv::INTER_LINEAR); imwrite(image_out_qiepian_zuoxia, img_qiepian_zuoxia); // 7、镜像逆时针8度 string image_jiangxiang_ni8 = "F:/小样本学习图片数据/xifang/生成后的train图片/旋转_镜像/镜像逆时针8度/"; string image_out_jiangxiang_ni8 = image_jiangxiang_ni8 + name; Mat img_jiangxiang_ni8 = rotateImage(img_jingxiang, -8); cv::resize(img_jiangxiang_ni8, img_jiangxiang_ni8, cv::Size(256, 256), cv::INTER_LINEAR); imwrite(image_out_jiangxiang_ni8, img_jiangxiang_ni8); // 8、镜像顺时针8度 string image_jiangxiang_shun8 = "F:/小样本学习图片数据/xifang/生成后的train图片/旋转_镜像/镜像顺时针8度/"; string image_out_jiangxiang_shun8 = image_jiangxiang_shun8 + name; Mat img_jiangxiang_shun8 = rotateImage(img_jingxiang, 8); cv::resize(img_jiangxiang_shun8, img_jiangxiang_shun8, cv::Size(256, 256), cv::INTER_LINEAR); imwrite(image_out_jiangxiang_shun8, img_jiangxiang_shun8); // 9、原图逆时针8度 string image_yuantu_ni8 = "F:/小样本学习图片数据/xifang/生成后的train图片/旋转_镜像/原图逆时针8度/"; string image_out_yuantu_ni8 = image_yuantu_ni8 + name; Mat img_yuantu_ni8 = rotateImage(image, -8); cv::resize(img_yuantu_ni8, img_yuantu_ni8, cv::Size(256, 256), cv::INTER_LINEAR); imwrite(image_out_yuantu_ni8, img_yuantu_ni8); // 10、原图顺时针8度 string image_yuantu_shun8 = "F:/小样本学习图片数据/xifang/生成后的train图片/旋转_镜像/原图顺时针8度/"; string image_out_yuantu_shun8 = image_yuantu_shun8 + name; Mat img_yuantu_shun8 = rotateImage(image, 8); cv::resize(img_yuantu_shun8, img_yuantu_shun8, cv::Size(256, 256), cv::INTER_LINEAR); imwrite(image_out_yuantu_shun8, img_yuantu_shun8); // 11、镜像噪声 string image_jingxiang_zao = "F:/小样本学习图片数据/xifang/生成后的train图片/噪声_镜像/镜像噪声/"; string image_out_jingxiang_zao = image_jingxiang_zao + name; Mat img_jingxiang_zao = addSaltNoise(img_jingxiang, 2000); cv::resize(img_jingxiang_zao, img_jingxiang_zao, cv::Size(256, 256), cv::INTER_LINEAR); imwrite(image_out_jingxiang_zao, img_jingxiang_zao); // 12、原图噪声 string image_yuantu_zao = "F:/小样本学习图片数据/xifang/生成后的train图片/噪声_镜像/原图噪声/"; string image_out_yuantu_zao = image_yuantu_zao + name; Mat img_yuantu_zao = addSaltNoise(image, 2000); cv::resize(img_yuantu_zao, img_yuantu_zao, cv::Size(256, 256), cv::INTER_LINEAR); imwrite(image_out_yuantu_zao, img_yuantu_zao); } } // resize void main000(void) { int i = 0; string name, clas; ifstream infile; infile.open("F:/小样本学习图片数据/xifang/org_img/val.txt"); string image_dir = "F:/小样本学习图片数据/xifang/org_img/val/"; string image_out = "F:/小样本学习图片数据/xifang/org_img/val_resize/"; while (infile) { infile >> name >> clas; cout << i++ << endl; string image_dir_name = image_dir + name; string image_out_name = image_out + name; Mat image = imread(image_dir_name, -1); Mat img_trans = image; cv::resize(img_trans, img_trans, cv::Size(256, 256), cv::INTER_LINEAR); imwrite(image_out_name, img_trans); } } // 对图像添加椒盐噪声 void main444(void) { string image_dir = "D:/visualstudio 2013/project text/c++/c++/"; string image_out_dir = "D:/visualstudio 2013/project text/c++/"; string image_name = "people_400.jpg"; string image_dir_name = image_dir + image_name; string image_out_dir_name = image_out_dir + image_name; Mat image = imread(image_dir_name, -1); Mat img_trans = addSaltNoise(image, 2000); imwrite(image_out_dir_name, img_trans); } // 对图像进行旋转 void main222(void) { string image_dir = "D:/visualstudio 2013/project text/c++/c++/"; string image_out_dir = "D:/visualstudio 2013/project text/c++/"; string image_name = "people_400.jpg"; string image_dir_name = image_dir + image_name; string image_out_dir_name = image_out_dir + image_name; int degree = 8; Mat image = imread(image_dir_name, -1); Mat img_trans = rotateImage(image, degree); cv::resize(img_trans, img_trans, cv::Size(256, 256), cv::INTER_LINEAR); imwrite(image_out_dir_name, img_trans); } // 对四角和中间进行切片 void main333(void) { string image_dir = "D:/visualstudio 2013/project text/c++/c++/"; string image_out_dir = "D:/visualstudio 2013/project text/c++/"; string image_name = "people_400.jpg"; string image_dir_name = image_dir + image_name; string image_out_dir_name = image_out_dir + image_name; Mat image = imread(image_dir_name, -1); Rect bbox(0, 0, 224, 224); // 左上角切片 //Rect bbox(image.cols - 1 - 224, 0, 224, 224); // 右上角切片 //Rect bbox(0, image.rows - 1 - 224, 224, 224); // 左下角切片 //Rect bbox(image.cols - 1 - 224, image.rows - 1 - 224, 224, 224); // 右下角切片 //Rect bbox(image.cols/2- 112, image.rows/2 -112,224, 224); // 中间切片 Mat img_trans = image(bbox); cv::resize(img_trans, img_trans, cv::Size(256, 256), cv::INTER_LINEAR); imwrite(image_out_dir_name, img_trans); } // 对图像进行水平镜像 void main111(void) { string image_dir = "D:/visualstudio 2013/project text/c++/c++/"; string image_out_dir = "D:/visualstudio 2013/project text/c++/"; string image_name = "people_400.jpg"; string image_dir_name = image_dir + image_name; string image_out_dir_name = image_out_dir + image_name; Mat image = imread(image_dir_name, -1); Mat img_trans; img_trans.create(image.size(), image.type()); for (int i = 0; i < image.rows; i++) { for (int j = 0; j < image.cols; j++) { img_trans.at<Vec3b>(i, j)[0] = image.at<Vec3b>(i, image.cols - 1 - j)[0]; img_trans.at<Vec3b>(i, j)[1] = image.at<Vec3b>(i, image.cols - 1 - j)[1]; img_trans.at<Vec3b>(i, j)[2] = image.at<Vec3b>(i, image.cols - 1 - j)[2]; } } imwrite(image_out_dir_name, img_trans); } // ******************************* 功能函数 *********************************** // 对图片添加椒盐噪声 Mat addSaltNoise(const Mat srcImage, int n) { Mat dstImage = srcImage.clone(); for (int k = 0; k < n; k++) { //随机取值行列 int i = rand() % dstImage.rows; int j = rand() % dstImage.cols; //图像通道判定 if (dstImage.channels() == 1) { dstImage.at<uchar>(i, j) = 255; //盐噪声 } else { dstImage.at<Vec3b>(i, j)[0] = 255; dstImage.at<Vec3b>(i, j)[1] = 255; dstImage.at<Vec3b>(i, j)[2] = 255; } } for (int k = 0; k < n; k++) { //随机取值行列 int i = rand() % dstImage.rows; int j = rand() % dstImage.cols; //图像通道判定 if (dstImage.channels() == 1) { dstImage.at<uchar>(i, j) = 0; //椒噪声 } else { dstImage.at<Vec3b>(i, j)[0] = 0; dstImage.at<Vec3b>(i, j)[1] = 0; dstImage.at<Vec3b>(i, j)[2] = 0; } } return dstImage; } // 对图像进行旋转函数,默认为顺时针方向 Mat rotateImage(Mat img, int degree) { degree = -degree;//warpAffine默认的旋转方向是逆时针,所以加负号表示转化为顺时针 double angle = degree * CV_PI / 180.; // 弧度 double a = sin(angle), b = cos(angle); int width = img.cols; int height = img.rows; int width_rotate = int(height * fabs(a) + width * fabs(b)); int height_rotate = int(width * fabs(a) + height * fabs(b)); //旋转数组map // [ m0 m1 m2 ] ===> [ A11 A12 b1 ] // [ m3 m4 m5 ] ===> [ A21 A22 b2 ] float map[6]; Mat map_matrix = Mat(2, 3, CV_32F, map); // 旋转中心 CvPoint2D32f center = cvPoint2D32f(width / 2, height / 2); CvMat map_matrix2 = map_matrix; cv2DRotationMatrix(center, degree, 1.0, &map_matrix2);//计算二维旋转的仿射变换矩阵 map[2] += (width_rotate - width) / 2; map[5] += (height_rotate - height) / 2; Mat img_rotate; //对图像做仿射变换 //CV_WARP_FILL_OUTLIERS - 填充所有输出图像的象素。 //如果部分象素落在输入图像的边界外,那么它们的值设定为 fillval. //CV_WARP_INVERSE_MAP - 指定 map_matrix 是输出图像到输入图像的反变换, warpAffine(img, img_rotate, map_matrix, Size(width_rotate, height_rotate), 1, 0, 0); return img_rotate; }
原图示意图:
水平镜像效果图:
原图左上角切片效果图:
原图顺时针旋转8度示意图:
原图添加椒盐噪声示意图: