数字图像处理实验(六):图像旋转与缩放

一、实验内容与原理

1、空间变换:

空间变换对应矩阵的仿射变换。一个坐标通过函数变换的新的坐标位置:
在这里插入图片描述
所以在程序中我们可以使用一个2*3的数组结构来存储变换矩阵:
在这里插入图片描述
以最简单的平移变换为例,平移(b1,b2)坐标可以表示为:
在这里插入图片描述
因此,平移变换的变换矩阵及逆矩阵记为:
在这里插入图片描述

2、缩放变换:

将图像横坐标放大(或缩小)sx倍,纵坐标放大(或缩小)sy倍,变换矩阵及逆矩阵为:
在这里插入图片描述

3、选择变换:

图像绕原点逆时针旋转a角,其变换矩阵及逆矩阵(顺时针,特别说明,图像的坐标轴与一般数学意义的坐标轴不同)为:
在这里插入图片描述

二、实验代码

实验环境:
(1)OpenCV3.4.3
(2)Ubuntu16.04
(3)VS Code
(4)C++

// 图像的旋转 与 缩放
#include   
#include 
#include 
#include 
#include 
#include 

class Extra1{
public:
    Extra1(std::vector path){
        for(int i = 0; i < path.size(); i++){
            // 读取彩色图片、灰度图片
            original_color_image.push_back(cv::imread(path[i]));
            original_gray_image.push_back(color2Gray(original_color_image[i]));
        }
    }
    // 0、彩色图像转灰度图像
    cv::Mat color2Gray(cv::Mat src_image){
        //创建与原图同类型和同大小的矩阵
	    cv::Mat gray_image(src_image.rows, src_image.cols, CV_8UC1);
        if(src_image.channels()!=1){
            for(int i = 0; i < src_image.rows; i++)
                for(int j = 0; j < src_image.cols; j++)
                    gray_image.at(i, j) = (src_image.at(i, j)[0] + src_image.at(i, j)[1] + src_image.at(i, j)[2]) / 3;
        }
        else
            gray_image = src_image.clone();
        return gray_image;
    }
    // 2 旋转图像
    void RotateScalingImage(cv::Mat& src_image, int opt=1){
        int angle = 0, delta = 1;
        std::string s[] = {"仅仅旋转","旋转加缩放"}; 
        while(true){
            double factor;
            if(opt)
                factor = (cos(angle*CV_PI/180.) + 1.05)*2;
            else
                factor = 1;

            int w = src_image.cols, h = src_image.rows;
            cv::Mat rot_mat = cv::Mat(2, 2, CV_32F);
            //             
            // [ m0 m1 m2 ]  ===> [ A11 A12   b1 ] ===> [cos(a)  sin(a)  b1]            
            // [ m3 m4 m5 ]  ===> [ A21 A22   b2 ] ===> [-sin(a) cos(a)  b2]
            //  
            rot_mat.at(0, 0) = (float)(factor*cos(-angle*2*CV_PI/180.));     
            rot_mat.at(0, 1) = (float)(factor*sin(-angle*2*CV_PI/180.));     
            rot_mat.at(1, 0) = -rot_mat.at(0, 1);     
            rot_mat.at(1, 1) = rot_mat.at(0, 0);                    
            // dst(x,y) = A * src(x,y) + b
            cv::Mat rotate_image = cv::Mat::zeros(src_image.rows, src_image.cols, src_image.type());
            realizeRotateScaling(src_image, rot_mat, rotate_image);
            //cv::Mat middle_filter_image = cv::Mat::zeros(rotate_image.rows, rotate_image.cols, rotate_image.type());
            grayFiltering(rotate_image);
            
            cv::imshow(s[opt], rotate_image);
            if(cv::waitKey(5) == 27)
                break;
            angle =(int)(angle + delta) % 360;   
        }
        return; 
    }
    // 2.1 实现旋转 与 缩放 操作
    void realizeRotateScaling(cv::Mat& src, cv::Mat& rotmat, cv::Mat& dst){
        int i, j, i1, j1;
        int centeri = src.rows/2, centerj = src.cols/2;
        for(i = 0; i < src.cols; i++)
            for(j = 0; j < src.rows; j++){
                i1 = (i - centeri)*rotmat.at(0, 0) + (j - centerj)*rotmat.at(1, 0) + centeri;
                j1 = (i - centeri)*rotmat.at(0, 1) + (j - centerj)*rotmat.at(1, 1) + centerj;
                if(0 <= i1 && i1 < dst.cols && 0 <= j1 && j1 < dst.rows)
                    dst.at(i1, j1) = src.at(i, j);
            }
    }
    // 3 灰度图像滤波
    void grayFiltering(cv::Mat& src, int select=0, int filter_size=9, double Q=1){
        int m = filter_size/2;
        int n = filter_size*filter_size;
        cv::Mat src_clone = src.clone();
        for(int i=m; i < src.rows - m; i++)
            for(int j=m; j < src.cols - m; j++){ 
                cv::Mat sub_matrix = src_clone(cv::Rect(j - m, i - m, filter_size, filter_size));
                if(src.at(i,j) == 0)
                    src.at(i,j) = maxValueConvolution(sub_matrix, filter_size);
            }
    }
    // 3.0 最大值滤波
    int maxValueConvolution(cv::Mat& image_block, int size){
        int max = 0;
        for(int i=0; i < image_block.rows; i++)
            for(int j=0; j < image_block.cols; j++){
                if(image_block.at(i, j) > max)
                    max = image_block.at(i, j);
            }
        return max;
    }
    // 3.1 中值滤波
    int middleValueConvolution(cv::Mat& image_block, int size=5){
        int min = 0, k = 0, pos = size*size/2;
        std::vector nums;
        for(int k1 = 0; k1 < size; k1++)
            for(int k2 = 0; k2 < size; k2++)
                nums.push_back(image_block.at(k1,k2));
        int middle = findMiddleNum(nums, 0, size*size - 1, pos);
        return middle;
    }
    // 3.2.1 快速查找中位数
    int findMiddleNum(std::vector& nums, int begin, int end, int n){
        int i = partition(nums, begin, end);
        if(i == n)
            return nums[i];
        else if(i > n)
            return findMiddleNum(nums, begin, i-1, n);
        else
            return findMiddleNum(nums, i+1, end, n);
    }
    // 3.2.2 交换
    void exchange(std::vector& nums, int a,int b){
        int c = nums[a];
        nums[a] = nums[b];
        nums[b] = c;
        return;
    }
    // 3.2.2 快速查找中位数
    int partition(std::vector& nums, int begin, int end){
        int i = begin, j = end + 1;
        int x = nums[begin];
        while (true) {
            while (nums[++i] < x) {// 向右扫描
                if (i == end)
                    break;
            }
            while (nums[--j] > x) {// 向左扫描
                if (j == begin)
                    break;
            }
            if (i >= j) // 指针相遇,切分位置确定
                break;
            exchange(nums, i, j);// 交换左右逆序元素
        }
        // 运行到最后:i指向从左往右第一个大于x的元素,j指向从右往左第一个小于x的元素。
        exchange(nums, begin, j);// 将切分元素放在切分位置
        return j;
    }
    //  运行
    void run(){
        RotateScalingImage(original_gray_image[0]);
    }


private:
    std::vector original_color_image;
    std::vector original_gray_image;
};

int main(){
    std::vector path;
    path.push_back("/home/lyd/image_process/pic/lena.jpg");
    Extra1 ex6(path);
    ex6.run();

    return 1;
}

三、实验结果

数字图像处理实验(六):图像旋转与缩放_第1张图片

数字图像处理实验(六):图像旋转与缩放_第2张图片

数字图像处理实验(六):图像旋转与缩放_第3张图片

你可能感兴趣的:(图像处理)