2000字范文,分享全网优秀范文,学习好帮手!
2000字范文 > opencv之图像翻转 平移 缩放 旋转 仿射学习笔记

opencv之图像翻转 平移 缩放 旋转 仿射学习笔记

时间:2022-02-14 07:28:36

相关推荐

opencv之图像翻转 平移 缩放 旋转 仿射学习笔记

opencv版本:opencv3.4.1

目录

1. 图像翻转(坐标映射)

2. 平移

3. 缩放

4. 旋转

1. 图像翻转(坐标映射)

int main(){cv::Mat srcImage = cv::imread("./lena.jpg");if(!srcImage.data){return -1;}int rows = srcImage.rows;int cols = srcImage.cols;//输出矩阵定义cv::Mat resultImage(rows, cols, srcImage.type());//x与y方向的矩阵cv::Mat xMapImage(rows, cols, CV_32FC1);cv::Mat yMapImage(rows, cols, CV_32FC1);//图像遍历for(int r = 0; r < rows; r++){for(int c = 0; c < cols; c++){//x与y均翻转xMapImage.at<float>(r,c) = cols-c;yMapImage.at<float>(r,c) = rows-r;}}remap(srcImage, resultImage, xMapImage, yMapImage, CV_INTER_LINEAR, cv::BORDER_CONSTANT,Scalar(0,0,0));cv::imwrite("resultImage.jpg", resultImage);}

效果:

2. 平移

有两种情况,(a)平移时图像大小保持不变; (b)平移时图像大小变化;

//平移不改变图像//参数:平移的图像,平移的x和y偏移量;cv::Mat imageTranslateNoChange(cv::Mat &srcImage, int xOffset, int yOffset){int nRows = srcImage.rows;int nCols = srcImage.cols;cv::Mat resultImage(nRows, nCols, srcImage.type());//遍历图像for(int r = 0 ; r < nRows; r++){for(int c = 0; c < nCols; c++){int x = c - xOffset;int y = r - yOffset;//边界判断;if(x >= 0 && y >= 0 && x < nCols && y < nRows){resultImage.at<cv::Vec3b>(r, c) = srcImage.ptr<cv::Vec3b>(y)[x];}}}return resultImage;}//平移,会改变图像cv::Mat imageTranslateChange(cv::Mat &srcImage, int xOffset, int yOffset){int nRows = srcImage.rows + abs(yOffset);//加上yint nCols = srcImage.cols + abs(xOffset);//加上xcv::Mat resultImage(nRows, nCols, srcImage.type());//遍历图像for(int r = 0 ; r < nRows; r++){for(int c = 0; c < nCols; c++){int x = c - xOffset;int y = r - yOffset;//边界判断;if(x >= 0 && y >= 0 && x < nCols && y < nRows){resultImage.at<cv::Vec3b>(r, c) = srcImage.ptr<cv::Vec3b>(y)[x];}}}return resultImage;}int main(){cv::Mat srcImage = cv::imread("./lena.jpg");if(!srcImage.data){return -1;}//cv::Mat resultImage = imageTranslateNoChange(srcImage, 200, 50);//cv::imwrite("translateNoChange.jpg", resultImage);cv::Mat resultImage = imageTranslateChange(srcImage, 80, 80);cv::imwrite("translateChange.jpg", resultImage);return 0;}

效果:

3. 缩放

//等间隔提取图像缩放cv::Mat imageEquidistant(cv::Mat& srcImage, float kx, float ky){//获取输出图像分辨率int nRows = cvRound(srcImage.rows * kx);int nCols = cvRound(srcImage.cols * ky);cv::Mat resultImage(nRows, nCols, srcImage.type());for(int i = 0; i < nRows; ++i){for(int j = 0; j < nCols; ++j){//根据水平因子计算坐标int x = static_cast<int>((i+1)/kx+0.5)-1;//根据垂直因子计算坐标int y = static_cast<int>((j+1)/ky+0.5)-1;resultImage.at<cv::Vec3b>(i, j) = srcImage.at<cv::Vec3b>(x,y);}}return resultImage;}static cv::Vec3b areaAverage(cv::Mat& srcImage, Point_<int> leftPoint, Point_<int> rightPoint){int temp1 = 0, temp2=0, temp3=0;//计算区域子块像素点个数int nPix = (rightPoint.x - leftPoint.x) * (rightPoint.y - leftPoint.y);//对区域子块各个通道对像素求和for(int i = leftPoint.x; i < rightPoint.x ;++i){for(int j = leftPoint.y; j < rightPoint.y; ++j){temp1 += srcImage.at<cv::Vec3b>(i,j)[0];temp2 += srcImage.at<cv::Vec3b>(i,j)[1];temp3 += srcImage.at<cv::Vec3b>(i,j)[2];}}//对每个通道求均值Vec3b vecTemp;vecTemp[0] = temp1 / nPix;vecTemp[1] = temp2 / nPix;vecTemp[2] = temp3 / nPix;return vecTemp;}//基于子块提取图像缩放cv::Mat imageRegionSubBlock(cv::Mat& srcImage, double kx, double ky){//获取输出图像分辨率int nRows = cvRound(srcImage.rows * kx);int nCols = cvRound(srcImage.cols * ky);cv::Mat resultImage(nRows, nCols, srcImage.type());//区域子块的左上角行列坐标int leftRowCoordinate = 0;int leftColCoordinate = 0;for(int i = 0; i < nRows; ++i){//根据水平因子计算坐标int x = static_cast<int>((i+1)/kx+0.5)-1;for(int j = 0; j < nCols; ++j){//根据垂直因子计算坐标int y = static_cast<int>((j+1)/ky+0.5)-1;//求解区域子块的均值;resultImage.at<Vec3b>(i, j) = areaAverage(srcImage,Point_<int>(leftRowCoordinate,leftColCoordinate),Point_<int>(x,y));//更新子块左上角的列坐标leftColCoordinate = y + 1;}leftColCoordinate = 0;//更新子块左上角的行坐标leftRowCoordinate = x + 1;}return resultImage;}

int main(){cv::Mat srcImage = cv::imread("./lena.jpg");if(!srcImage.data){return -1;}cv::Mat resultImage;//resultImage = imageEquidistant(srcImage, 0.5, 0.5);resultImage = imageRegionSubBlock(srcImage, 0.5, 0.5);cv::imwrite("RegionSubBlock.jpg", resultImage);return 0;}

效果:

4. 旋转

cv::Mat imageRotate(cv::Mat& srcImage, int angle){//角度转换float alpha = angle * CV_PI / 180;//构造旋转矩阵float rotateMat[3][3] = {{cos(alpha), -sin(alpha), 0},{sin(alpha), cos(alpha), 0},{0 , 0, 1}};int nSrcRows = srcImage.rows;int nSrcCols = srcImage.cols;//计算旋转后图像矩阵的各个顶点位置float a1 = nSrcCols * rotateMat[0][0] ;float b1 = nSrcCols * rotateMat[1][0] ;float a2 = nSrcCols * rotateMat[0][0] + nSrcRows * rotateMat[0][1];float b2 = nSrcCols * rotateMat[1][0] + nSrcRows * rotateMat[1][1];;float a3 = nSrcRows * rotateMat[0][1] ;float b3 = nSrcRows * rotateMat[1][1] ;int kxMin = min(min(min(0.0f,a1),a2),a3);int kxMax = max(max(max(0.0f,a1),a2),a3);int kyMin = min(min(min(0.0f,b1),b2),b3);int kyMax = max(max(max(0.0f,b1),b2),b3);//计算输出矩阵的尺寸int nRows = abs(kxMax - kxMin);int nCols = abs(kyMax - kyMin);cv::Mat dst(nRows, nCols, srcImage.type(), cv::Scalar::all(0));for(int i = 0; i < nRows; ++i){for(int j = 0 ; j < nCols; ++j){//旋转坐标转换int x = (j + kxMin) * rotateMat[0][0] - (i + kyMin) * rotateMat[0][1];int y = -(j + kxMin) * rotateMat[1][0] + (i + kyMin) * rotateMat[1][1];//区域旋转if((x >= 0) && (x < nSrcCols) && (y >= 0) && y < nSrcRows){dst.at<cv::Vec3b>(i, j) = srcImage.at<cv::Vec3b>(y,x);}}}return dst;}

4.1 旋转30和60度;

int main(){cv::Mat srcImage = cv::imread("./lena.jpg");if(!srcImage.data){return -1;}cv::Mat resultImage;//resultImage = imageRotate(srcImage,30);resultImage = imageRotate(srcImage,60);cv::imwrite("rotate60.jpg", resultImage);return 0;}

效果:

图像翻转是图像旋转的特例,opencv中提供了traspose与filp函数对图像进行矩阵转置变换;可以将图像进行水平或垂直翻转;

4.2 图像翻转

int main(){cv::Mat srcImage = cv::imread("./lena.jpg");if(!srcImage.data){return -1;}cv::Mat resultImage;//transpose(srcImage, resultImage);//逆时针旋转90;//flip( srcImage, resultImage, 0); //垂直翻转//flip( srcImage, resultImage, 1); //水平翻转//flip( srcImage, resultImage, -1);//垂直和水平翻转cv::imwrite("flip-1.jpg", resultImage);return 0;}

效果:

5. 仿射变换

int main(){cv::Mat srcImage = cv::imread("./lena.jpg");if(!srcImage.data){return -1;}int nRows = srcImage.rows;int nCols = srcImage.cols;//定义仿射变换的二维点数组//源图像和目标图像对应映射的三个点cv::Point2f srcPoint[3];cv::Point2f resPoint[3];srcPoint[0] = cv::Point2f(0, 0);srcPoint[1] = cv::Point2f(nCols-1, 0);srcPoint[2] = cv::Point2f(0,nRows-1);resPoint[0] =cv::Point2f(nCols*0, nRows*0.33);resPoint[1] =cv::Point2f(nCols*0.85, nRows*0.25);resPoint[2] =cv::Point2f(nCols*0.15, nRows*0.7);//定义仿射变换矩阵cv::Mat warpMat(cv::Size(2,3), CV_32F);cv::Mat resultImage;cv::Mat::zeros(nRows, nCols, srcImage.type());//计算仿射变换矩阵,即仿射变换的2x3数组warpMat = cv::getAffineTransform(srcPoint, resPoint);//根据仿射矩阵计算图像仿射变换cv::warpAffine(srcImage, resultImage, warpMat, cv::Size(resultImage.rows,resultImage.cols));cv::imwrite("warpAffine.jpg", resultImage);#if 1//设置仿射变换参数cv::Point2f centerPoint = cv::Point2f(nCols/2, nRows/2);double angle = -50;double scale = 0.7;//获取仿射变换矩阵warpMat = getRotationMatrix2D(centerPoint, angle, scale);//对源图像进行角度仿射变换cv::warpAffine(srcImage, resultImage, warpMat, cv::Size(resultImage.rows,resultImage.cols));#endif cv::imwrite("warpAffine-angle.jpg", resultImage);return 0;}

效果:

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。