本文共 8209 字,大约阅读时间需要 27 分钟。
新建一个图像,他的大小比原来的图像要大一些,因为平移后图像位置发生变化,图像被移动后,会有一部分位置空出来。平移前和平移后的效果图如图所示:
【原图】 【平移后的图像】原图和平移后的图像相比,很明显,红色框框住的那部分是平移后空出来的部分。
所以平移思路就是,将原先图像的横坐标和纵坐标分别加上一个数字,变成一个新的坐标,然后将原图中原坐标位置的RGB赋值给新图中新坐标。//读原图 Mat image; image = imread("pic.jpg", CV_LOAD_IMAGE_COLOR); if (!image.data) { cout << "找不到图片或无法打开图片\n"; return -1; } namedWindow("image_source", CV_WINDOW_AUTOSIZE); imshow("原图", image); //--------------------平移变换-------------- int dx = 10, dy = 20; Mat image_shift(image.rows + dx, image.cols+dy, CV_8UC3);//新建一个大于原图的图像,备用 //一个个像素进行处理 for (int counter1 = 0; counter1 < image.rows; counter1++) { for (int counter2 = 0; counter2 < image.cols; counter2++) { //将原坐标进行平移,并将原坐标上的RGB值赋给新坐标 image_shift.at(counter1+dx, counter2+dy)[0] = image.at (counter1, counter2)[0]; image_shift.at (counter1+dx, counter2 + dy)[1] = image.at (counter1, counter2)[1]; image_shift.at (counter1+dx , counter2+ dy)[2] = image.at (counter1, counter2)[2]; } } //imshow("平移", image_shift); imwrite("1.jpg", image_shift);//将平移后的图像存储为名称为1.jpg的文件 //-------------- 平移完成-------------------
//----------------尺度变换------------------ double mul_num = 0.8;//大于1是放大,小于1是缩小 int row_num = (int)floor(image.rows * mul_num), col_num = (int)floor(image.cols * mul_num); Mat image_scale(row_num, col_num, CV_8UC3); for (int counter1 = 0; counter1 < row_num; counter1++) { for (int counter2 = 0; counter2 < col_num; counter2++) { //将筛孔缩小,对上画的大小 int x = (int)1.0 / mul_num *counter1, y = (int)1.0 / mul_num *counter2; image_scale.at(counter1, counter2 )[0] = image.at (x, y)[0]; image_scale.at (counter1, counter2 )[1] = image.at (x, y)[1]; image_scale.at (counter1, counter2 )[2] = image.at (x, y)[2]; } } //imshow("尺度变换", image_scale); imwrite("2.jpg", image_scale);//存储变换后的图像 //----------------尺度变换完成---------------
//----------------旋转变换------------------ double angle = 135.0 * 3.1415926 / 180.0;//把角度化成弧度 int dis = ceil(sqrt(pow(image.rows, 2) + pow(image.cols, 2)));//新图像的长宽应该是原图像的对角线长度 Mat image_nrota(dis, dis, CV_8UC3); for (int counter1 = 0; counter1 < image.rows; counter1++) { for (int counter2 = 0; counter2 < image.cols; counter2++) { //计算应该平移的距离 float cenX = image_nrota.rows/2 - ((image.rows / 2) * cos(angle) - (image.cols/2) * sin(angle)), cenY = image_nrota.cols/2 - ((image.rows / 2) * sin(angle) + (image.cols / 2) * cos(angle)); //按照仿射矩阵计算后进行平移 int x = counter1 * cos(angle) - counter2 * sin(angle) + cenX, y = counter1 * sin(angle) + counter2 * cos(angle) + cenY; image_nrota.at(x, y)[0] = image.at (counter1, counter2)[0]; image_nrota.at (x, y)[1] = image.at (counter1, counter2)[1]; image_nrota.at (x, y)[2] = image.at (counter1, counter2)[2]; } } //imshow("旋转", image_nrota); imwrite("3.jpg", image_nrota); //-----------旋转变换完成---------------
【change.h】
#pragma once#include#include #include #include #include using namespace std;using namespace cv;//对图像进行平移操作void shift(Mat &image, int dx, int dy){ Mat image_shift(image.rows + dx, image.cols + dy, CV_8UC3);//新建一个大于原图的图像,备用 //一个个像素进行处理 for (int counter1 = 0; counter1 < image.rows; counter1++) { for (int counter2 = 0; counter2 < image.cols; counter2++) { //将原坐标进行平移,并将原坐标上的RGB值赋给新坐标 image_shift.at (counter1 + dx, counter2 + dy)[0] = image.at (counter1, counter2)[0]; image_shift.at (counter1 + dx, counter2 + dy)[1] = image.at (counter1, counter2)[1]; image_shift.at (counter1 + dx, counter2 + dy)[2] = image.at (counter1, counter2)[2]; } } //imshow("平移", image_shift); imwrite("1.jpg", image_shift);//将平移后的图像存储为名称为1.jpg的文件}//进行尺度变换void scale(Mat &image, double mul_num){ int row_num = (int)floor(image.rows * mul_num), col_num = (int)floor(image.cols * mul_num); Mat image_scale(row_num, col_num, CV_8UC3); for (int counter1 = 0; counter1 < row_num; counter1++) { for (int counter2 = 0; counter2 < col_num; counter2++) { //将筛孔缩小,对上画的大小 int x = (int)1.0 / mul_num * counter1, y = (int)1.0 / mul_num * counter2; image_scale.at (counter1, counter2)[0] = image.at (x, y)[0]; image_scale.at (counter1, counter2)[1] = image.at (x, y)[1]; image_scale.at (counter1, counter2)[2] = image.at (x, y)[2]; } } //imshow("尺度变换", image_scale); imwrite("2.jpg", image_scale);//存储变换后的图像}//进行旋转void rotation(Mat &image, double angle_in){ double angle = angle_in * 3.1415926 / 180.0;//把角度化成弧度 int dis = ceil(sqrt(pow(image.rows, 2) + pow(image.cols, 2)));//新图像的长宽应该是原图像的对角线长度 Mat image_nrota(dis, dis, CV_8UC3); for (int counter1 = 0; counter1 < image.rows; counter1++) { for (int counter2 = 0; counter2 < image.cols; counter2++) { //计算应该平移的距离 float cenX = image_nrota.rows / 2 - ((image.rows / 2) * cos(angle) - (image.cols / 2) * sin(angle)), cenY = image_nrota.cols / 2 - ((image.rows / 2) * sin(angle) + (image.cols / 2) * cos(angle)); //按照仿射矩阵计算后进行平移 int x = counter1 * cos(angle) - counter2 * sin(angle) + cenX, y = counter1 * sin(angle) + counter2 * cos(angle) + cenY; image_nrota.at (x, y)[0] = image.at (counter1, counter2)[0]; image_nrota.at (x, y)[1] = image.at (counter1, counter2)[1]; image_nrota.at (x, y)[2] = image.at (counter1, counter2)[2]; } } //imshow("旋转", image_nrota); imwrite("3.jpg", image_nrota);}//垂直偏移变换void voffset(Mat &image, double sv){ Mat image_voffset(sv*image.rows + image.cols, image.cols, CV_8UC3); for (int counter1 = 0; counter1 < image.rows; counter1++) { for (int counter2 = 0; counter2 < image.cols; counter2++) { int x = counter1 * sv + counter2; image_voffset.at (x, counter2)[0] = image.at (counter1, counter2)[0]; image_voffset.at (x, counter2)[1] = image.at (counter1, counter2)[1]; image_voffset.at (x, counter2)[2] = image.at (counter1, counter2)[2]; } } //imshow("垂直偏移", image_voffset); imwrite("4.jpg", image_voffset);}//水平偏移变换void hoffset(Mat &image, double sh){ Mat image_hoffset(image.rows, sh*image.rows + image.cols, CV_8UC3); for (int counter1 = 0; counter1 < image.rows; counter1++) { for (int counter2 = 0; counter2 < image.cols; counter2++) { int y = counter1 * sh + counter2; image_hoffset.at (counter1, y)[0] = image.at (counter1, counter2)[0]; image_hoffset.at (counter1, y)[1] = image.at (counter1, counter2)[1]; image_hoffset.at (counter1, y)[2] = image.at (counter1, counter2)[2]; } } //imshow("水平偏移", image_hoffset); imwrite("5.jpg", image_hoffset);}
【main.cpp】
#include#include #include #include #include #include "change.h"using namespace std;using namespace cv;int main(){ //读原图 Mat image; image = imread("pic.jpg", CV_LOAD_IMAGE_COLOR); if (!image.data) { cout << "找不到图片或无法打开图片\n"; return -1; } namedWindow("image_source", CV_WINDOW_AUTOSIZE); imshow("原图", image); //平移 shift(image, 10, 20); //缩放 scale(image, 0.8); //旋转 rotation(image, 45); //垂直偏移 voffset(image, 1); //水平偏移 hoffset(image, 1); //连续播放变换后的图像 string picname = ""; Mat image2; for (int counter = 1; counter < 6; counter++) { picname = '0'+ counter; picname += ".jpg"; image2 = imread(picname,CV_LOAD_IMAGE_COLOR); imshow("变换后的图像", image2); waitKey(3000); } waitKey(0); return 0;}