zoukankan      html  css  js  c++  java
  • 图像处理方法(膨胀腐蚀,霍夫变换,滤波,去噪,图像增强,二值化,图片旋转,画直线)

    OpenCV 基础,常用方法
    
    导入头文件
    #include <opencv2/opencv.hpp>
    #include <opencv2/highgui/highgui.hpp>
    #include <opencv2/imgproc/imgproc.hpp>
    using namespace cv;
    using namespace std;
    //读取图片
    void fun_imread(Mat img) {
        Mat img1;
        imshow("原图", img);//图像显示
        waitKey();//读入图片显示时间waitKey(6000);显示6000毫秒,如果写,就一直显示
    }
    //腐蚀操作函数
    void fun_fs(Mat img) {
        //进行腐蚀操作
        //卷积核所覆盖下的原图对应区域内的所有像素的最小值,用这个最小值替换当前像素值。图片通过这种局部颜色加深,
        //导致整体颜色加深
        Mat element = getStructuringElement(MORPH_RECT, Size(10, 10));// Size的参数是卷积核的大小,越大腐蚀越严重。
        //Mat element = getStructuringElement(MORPH_RECT, Size(15, 15));
        Mat dstImage;
        erode(img, dstImage, element);
        imshow("腐蚀操作后的图", dstImage);//腐蚀操作的函数
        waitKey();
    }
    //膨胀
    void fun_pz(Mat img) {
        //腐蚀和膨胀区别是函数imshow("膨胀操作后的图", dstImage)//和池化操作类似
        //卷积核所覆盖下的原图对应区域内的所有像素的最大,用这个最小值替换当前像素值。图片通过这种局部颜色变浅,
        //导致整体颜色变浅
        Mat element = getStructuringElement(MORPH_RECT, Size(10, 10));// Size的参数是卷积核的大小,越大腐蚀越严重。
        //Mat element = getStructuringElement(MORPH_RECT, Size(15, 15)); //getStructuringElement获取结构元素
        Mat dstImage;
        dilate(img, dstImage, element);//第一个参数是输入图片,第二个参数是输出图片,第三个是
        imshow("膨胀操作后的图", dstImage); //膨胀操作的函数
        waitKey();
    }
    均值滤波
    void fun_mh(Mat img) {
        //图片模糊的本质是对图片进行均值滤波,就是均值池化类似的操作
        Mat dstImage;
        blur(img, dstImage, Size(7, 7));//均值滤波
        imshow("均值滤波【效果图】", dstImage);
        waitKey();
    }
        //中值滤波  中值滤波可以有效滤除椒盐噪声
        medianBlur(img1, img2, 3); //也会变模糊,但程度相对较小
        imshow("中值滤波后", img2);
        //均值滤波 均值滤波能够滤除白噪声,但会使原始图像丢掉一些细节(原图变得模糊)
        blur(img1, img2, Size(3,3)); 
        imshow("均值滤波后", img2);
        //高斯滤波 一般图像采取的都是高斯滤波
        //加权均值滤波(高斯滤波)也可以有效的滤除白噪声,同时不会丢掉原图中的细节(甚至原图更清晰)
        GaussianBlur(img1, img2, Size(3,3),5);//size的大小调节不好会报错size越大越模糊
        imshow("高斯滤波后", img2);
    
    //转灰度图,进行边缘轮廓检测
    void fun_hd(Mat img) {
        //将图片变成灰度图
        Mat dstImage,img1;
        blur(img, dstImage, Size(4, 4));//1、均值滤波
        cvtColor(dstImage, dstImage, COLOR_BGR2GRAY);//2、转成灰度图
        cout << dstImage.at<Vec3b>(2, 2)[1];
        imshow("灰度图", dstImage);
        Canny(dstImage, img1, 50, 120, 3); //3、使用边缘检测
        //canny 第一个数字越大
        imshow("边缘检测", img1);
        waitKey(0);
    }
    
    void fun(Mat img1) {
        Mat img;
        //创建相同大小相同类型的矩阵
        img.create(img1.size(),img1.type());
        img.create(img1.size(), CV_32FC3);
        img = img1.clone();
        img.rows;//
        img.cols;//
    }
    
    void fun_readvido() {
        //如果有视屏,则读取视屏,如果没有视屏参数写0,调用本地摄像头
        //VideoCapture cap("C:\Users\MH\Desktop\常用工具类\壁纸\1.avi");
        VideoCapture cap(0);
        while(1) {
            Mat frame;
            cap >> frame;
            Mat dstImage, img1;
            imshow("读取视屏", img1);
            waitKey(10);
        }
    }
    
    //随机产生椒盐噪声
    Mat fun_1(Mat img1, int k) {
        Mat img = img1.clone();
        int i, j;
        for (int m = 0; m < k; m++) {//循环k次,随机产生k个点
            i = rand() % img.rows; //img.at<Vec3b>(i, j)[0] = 0; i代表行下标(高rows),j代表列下标写反位置会报错
            j = rand() % img.cols;//产生随机的下标点
            img.at<Vec3b>(i, j)[0] = 0;
            img.at<Vec3b>(i, j)[1] = 0;
            img.at<Vec3b>(i, j)[2] = 0;
        }
        for (int m = 0; m <int(k / 2); m++) {
            i = rand() % img.rows;
            j = rand() % img.cols;
            img.at<Vec3b>(i, j)[0] = 255;
            img.at<Vec3b>(i, j)[1] = 255;
            img.at<Vec3b>(i, j)[2] = 255;
        }
        return img;
    }
    //log图像增强
    Mat fun_log(Mat img) {
        Mat img1;
        float C = 0.5;
        img1.create(img.size(), CV_32FC3);
        for (int i = 0; i < img.rows; i++) {
            for (int j = 0; j < img.cols; j++) {
                img1.at<Vec3f>(i, j)[0] = C * log(1+float(img.at<Vec3b>(i, j)[0]));
                img1.at<Vec3f>(i, j)[1] = C * log(1+float(img.at<Vec3b>(i, j)[1]));
                img1.at<Vec3f>(i, j)[2] = C * log(1+float(img.at<Vec3b>(i, j)[2]));
            }
        }
        //归一化到0~255  
        normalize(img1, img1, 0, 255, CV_MINMAX);
        //转换成8bit图像显示  
        convertScaleAbs(img1, img1);
        return img1;
    }
    
    //指数对图片进行放暗
    Mat fun_3(Mat img) {
        int c = 3;
        float b = 0.1;
        Mat img1;
        //img1 = img.clone();
        img1.create(img.size(), CV_32FC3);//32位的图像像素灰度值在(0-1)之间的显示是正常显示,也可以将其转化成0-255,然后转乘8bit的图
        for (int m = 0; m < img.rows; m++) {
            for (int j = 0; j < img.cols; j++) {
                img1.at<Vec3f>(m, j)[0] = float(img.at<Vec3b>(m, j)[0]) / 255 * float(img.at<Vec3b>(m, j)[0]) / 255;
                img1.at<Vec3f>(m, j)[1] = float(img.at<Vec3b>(m, j)[1]) / 255 * float(img.at<Vec3b>(m, j)[1]) / 255;
                img1.at<Vec3f>(m, j)[2] = float(img.at<Vec3b>(m, j)[2]) / 255 * float(img.at<Vec3b>(m, j)[2]) / 255;
            }
        }
        return img1;
    }
    
    
    
    //霍夫变换+图像旋转校正+背景填充
    //二值化
    Mat fun_two(Mat img) {
        float a = 110;
        for (int i = 0; i < img.rows; i++) {
            for (int j = 0; j < img.cols; j++) {
                if (0.3*img.at<Vec3b>(i, j)[0] + 0.6*img.at<Vec3b>(i, j)[1] + 0.1*img.at<Vec3b>(i, j)[2] > a) {
                    img.at<Vec3b>(i, j)[0] = 255;
                    img.at<Vec3b>(i, j)[1] = 255;
                    img.at<Vec3b>(i, j)[2] = 255;
                }
                else
                {
                    img.at<Vec3b>(i, j)[0] = 0;
                    img.at<Vec3b>(i, j)[1] = 0;
                    img.at<Vec3b>(i, j)[2] = 0;
                }
            }
        }
        return img;
    }
    
    //背景
    Mat fun_bj(Mat img, float a, float b, float c) {
        for (int i = 0; i < img.rows; i++) {
            for (int j = 0; j < img.cols; j++) {
                if (0.3*img.at<Vec3b>(i, j)[0] + 0.6*img.at<Vec3b>(i, j)[1] + 0.1*img.at<Vec3b>(i, j)[2] == 255) {
                    img.at<Vec3b>(i, j)[0] = a;
                    img.at<Vec3b>(i, j)[1] = b;
                    img.at<Vec3b>(i, j)[2] = c;
                }
                else
                {
                    img.at<Vec3b>(i, j)[0] = 0;
                    img.at<Vec3b>(i, j)[1] = 0;
                    img.at<Vec3b>(i, j)[2] = 0;
                }
            }
        }
        return img;
    }
    
    //画线的函数
    void fun_line(vector<Vec2f>  lines, Mat img) {
        for (size_t i = 0; i < lines.size(); i++)
        {
            float rho = lines[i][0];
            float theta = lines[i][1];
            double a = cos(theta), b = sin(theta);
            double x0 = a * rho, y0 = b * rho;
            Point pt1(cvRound(x0 + 1000 * (-b)),
                cvRound(y0 + 1000 * (a)));
            Point pt2(cvRound(x0 - 1000 * (-b)),
                cvRound(y0 - 1000 * (a)));
            line(img, pt1, pt2, Scalar(0, 0, 255), 3, 8);
            
        }
        imshow("线性图", img);
    }
    
    //图片旋转//放射变换
    Mat rotateImage(Mat img, double jd)
    {
        Mat img1;
        //旋转中心为图像中心    
        Point2f center;
        center.x = float(img.cols / 2.0);
        center.y = float(img.rows / 2.0);
        int length = 0;
        length = sqrt(img.cols*img.cols + img.rows*img.rows);
        //计算二维旋转的仿射变换矩阵  
        Mat M = getRotationMatrix2D(center, jd, 1);
        warpAffine(img, img1, M, Size(length, length), 1, 0, Scalar(255, 255, 255));//仿射变换,背景色填充为白色
        return img1;
    }
    
    
    int main()
    {
        Mat imroa, img3;
        float a, b, c;//
        imroa = imread("C:\Users\MH\Desktop\pInFileName.jpg");
        a = imroa.at<Vec3b>(int(imroa.rows*0.9), int(imroa.rows*0.6))[0];
        b = imroa.at<Vec3b>(int(imroa.rows*0.9), int(imroa.rows*0.6))[1];
        c = imroa.at<Vec3b>(int(imroa.rows*0.9), int(imroa.rows*0.6))[2];
        imshow("原图", imroa);
        for (int i = 0; i < 10; i++)
        {
            medianBlur(imroa, imroa, 7);//第三个参数一般设为奇数
    
        }
        blur(imroa, imroa, Size(5, 5));
    
        img3 = imroa.clone();
    
        cvtColor(imroa, imroa, COLOR_BGR2GRAY);
    
        Canny(imroa, imroa, 50, 200, 3);
    
        vector<Vec2f> lines;
        //霍夫变换,获取直线对象
        HoughLines(imroa, lines, 1, CV_PI / 180, 300, 0, 0);
        //// 输入,线条对象,极径的步长,角度的步长,阈值(阈值越大对直线要求越高,提取的直线数量越少)
        float sum = 0;
        for (size_t i = 0; i < lines.size(); i++) {
            sum += lines[i][1];
        }
        float jd = sum / lines.size() / CV_PI * 180;
        cout << lines.size() << endl;
        cout << jd;
        //二值化
        img3 = fun_two(img3);
    
        fun_line(lines,img3);
    
        Mat img2;
        //旋转
        img2 = rotateImage(img3, jd);
        //imshow("中值滤波后", imroa);
        //imroa = fun_two(imroa);
        //imshow("二值化", imroa);
    
        //背景颜色填充裁剪
        Mat img4;
        fun_bj(img2, a, b, c);
    
        imshow("填充", img2);
    
        waitKey();
        return 0;
    }
    
     
    图像处理的基本思路:

  • 相关阅读:
    TP框架 商城前台用户注册方法
    小知识
    TP框架中的一些登录代码分享
    js贪吃蛇小游戏
    关于jQ的小案例分享
    vb语法
    ruby file
    ruby的next if boolean
    ruby文件操作
    vue里面的this指向
  • 原文地址:https://www.cnblogs.com/zgl19991001/p/11420844.html
Copyright © 2011-2022 走看看