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度示意图:
原图添加椒盐噪声示意图: