opencv版本:opencv3.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);
- }
效果:
有两种情况,(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
(r, c) = srcImage.ptr(y)[x]; - }
-
- }
- }
-
- return resultImage;
- }
-
- //平移,会改变图像
- cv::Mat imageTranslateChange(cv::Mat &srcImage, int xOffset, int yOffset)
- {
- int nRows = srcImage.rows + abs(yOffset);//加上y
- int nCols = srcImage.cols + abs(xOffset);//加上x
-
- 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
(r, c) = srcImage.ptr(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;
- }
效果:
- //等间隔提取图像缩放
- 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
(i, j) = srcImage.at(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
(i,j)[0]; - temp2 += srcImage.at
(i,j)[1]; - temp3 += srcImage.at
(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
(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;
- }
效果:
- 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
(i, j) = srcImage.at(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;
- }
效果: