• 【图像处理】openCV库教程


    openCV 基础学习

    with:于士琪openCV基础


    env:opencv3.4.0+vc2017集成开发环境

    图像的表示:矩阵

    1. 灰度矩阵 <br>
    2. 彩色(多通道)如RGB图像,RGB图像的通道顺序是BGR
    

    Mat

    class CV_EXPORTS Mat
    	{
    	public:
    	//一系列函数
    	...
    	/* flag 参数中包含许多关于矩阵的信息,如:
    	-Mat 的标识
    	-数据是否连续
    	-深度
    	-通道数目
    	*/
    	int flags;
    	//矩阵的维数,取值应该大于或等于 2
    	int dims;
    	//矩阵的行数和列数,如果矩阵超过 2 维,这两个变量的值都为-1
    	int rows, cols;
    	//指向数据的指针
    	uchar* data;
    	//指向引用计数的指针
    	//如果数据是由用户分配的,则为 NULL
    	int* refcount;
    	24
    	//其他成员变量和成员函数
    	...
    	};
    	
    

    创建Mat对象(构造方法):

    1. Mat M(3,2,CV_8UC3,Scalar(0,0,255));

      //创建一个行数为3,列数为2的图像,图像元素是8位无符号整数,3个通道,初始值为0,0,255,为全红
    2. Mat对象的type是:CV_8UC1,CV_16SC1,…,CV_64FC4 等
    3. create()方法
    4. at()方法:读矩阵中某个像素,或对某个元素赋值
        uchar value = grayim.at<uchar>(i,j);//读出第 i 行第 j 列像素值
        grayim.at<uchar>(i,j)=128; //将第 i 行第 j 列像素值设置为 128
    
    1. 迭代器使用 MatIterator
    #include<iostream>
    #include<opencv2opencv.hpp>
    using namespace std;
    using namespace cv;
    
    int main() {
    	Mat g(600, 800, CV_8UC1);
    	Mat c(600, 800,CV_8UC3);
    	MatIterator_<uchar> git, gend;
    	MatIterator_<Vec3b> cit, cend;
    	for (git = g.begin<uchar>(), gend = g.end<uchar>();git != gend;++git) {
    		*git = rand() % 255;
    	}
    	for (cit = c.begin<Vec3b>(), cend = c.end<Vec3b>();cit != cend;++cit) {
    		(*cit)[0] = rand() % 255;
    		(*cit)[1] = rand() % 255;
    		(*cit)[2] = rand() % 255;
    	}
    	imshow("g", g);
    	imshow("c", c);
    	waitKey(0);
    	return 0;
    
    }
    
    1. 选取图像局部区域:是浅复制,注意复制前后共享内存区域。

      i. 单行、列选取
      row()/col()

         Mat Mat::row(int i) const
         Mat Mat::col(int j) const
      

      ii. 多行、多列

      Range类:

      	class Range
      	{
      	public:
      	int start, end; //从start行(列)到end行(列),左闭右开
      	
      	static .. all(); //all方法,静态方法,表示所有的行、列
      	
      	};
      
       如:
      
      	Mat A = Mat::eye(10,10,CV_32S);
      	//提取第一列到第三列
      	Mat B = A(Range::all(),Range(1,3));
      	//提取第一行到第三行
      	Mat C = A(Range(1,3),Range::all());
      	
      
    2. Mat_类:Mat类的封装:

      使用 Mat_类,那么就可以在变量声明时确定元素的类型,访问元素时不再需要指定元素类型,即使得代码简洁

    图像读写:读写图像文件:

    1. imread
    Mat imread(const string& filename, int flags=1 );
    
    	imread()函数返回的是 Mat 对象.
    	如果读取文件失败,则会返回一个空矩阵,即 Mat::data 的值是 NULL。执行 imread()之后,需要检查文件是否成功读入,可以使用 Mat::empty()函数进行检查。
    			flag 参数值有三种情况:
    			  flag>0,该函数返回 3 通道图像,如果磁盘上的图像文件是单通道的灰度图像,则会被强制转为 3 通道;
    			  flag=0,该函数返回单通道图像,如果磁盘的图像文件是多通道图像,则会被强制转为单通道;
    			  flag<0,则函数不对图像进行通道转换。
    
    1. imwrite
        bool imwrite(const string& filename, InputArray image,const vector<int>& params=vector<int>())
    
    1. 读入一副图像,然后对图像进行 Canny 边缘操作:
        #include<iostream>
        #include<opencv2opencv.hpp>
        using namespace std;
        using namespace cv;
    
        int  main() {
        	Mat im = imread("C:\Users\duye\Desktop\2.jpg",1);
    	if (im.empty()) {
    		cout << "Can not load image!" << endl;
    		return -1;
    	}
    	Mat result;
    	Canny(im, result, 50, 100);
    	imwrite("C:\Users\duye\Desktop\1.jpg",result);
    
    	return 0;
    
        }
    

    视频操作:

    1. 读视频:
      VideoCapture 既可以从视频文件读取图像,也可以从摄像头读取图像

      从文件/视频读视频:
        #include <iostream>
        #include "opencv2/opencv.hpp"
        using namespace std;
        using namespace cv;
        int main(int argc, char** argv)
        {
        //打开视频文件
            VideoCapture cap("video.short.raw.avi");
            //根据摄像头ip 获取实时视频流
            //注意这里不再使用定义了的返回的视频流,直接使用摄像头ip就好
            //String videoUrl = "...";
            //VideoCapture cap;
            //cap.open(videoUrl);
            //检查是否成功打开
            if(!cap.isOpened())
            {
                cerr << "Can not open a camera or file." << endl;
                return -1;
            }
            Mat edges;
            //创建窗口
            namedWindow("edges",1);
            for(;;)
            {
                Mat frame;
                //从 cap 中读一帧,存到 frame
                cap >> frame;
                //如果未读到图像
                if(frame.empty())
                    break;
                //将读到的图像转为灰度图
                cvtColor(frame, edges, CV_BGR2GRAY);
                //进行边缘提取操作
                Canny(edges, edges, 0, 30, 3);
                //显示结果
                imshow("edges", edges);
                //等待 30 秒,如果按键则推出循环
                if(waitKey(30) >= 0)
                    break;
            }
            //退出时会自动释放 cap 中占用资源
            return 0;
        }
    
    1. 写视频

      读取摄像头视频,写入文件中保存
        #include <opencv2/core/core.hpp>  
        #include <opencv2/highgui/highgui.hpp>  
        using namespace cv;
        void main()
        {
        	String url = "http://192.168.1.1:8080";
    	VideoCapture cap();
    	cap.open(url);
    	double rate = 25.0;//视频的帧率
    	Size videoSize(1280,960);
    	VideoWriter writer("VideoTest.avi", CV_FOURCC('M', 'J', 'P', 'G'), rate, videoSize);
    	Mat frame;
    	while (capture.isOpened())
    	{
    		capture >> frame;
    		writer << frame;
    		imshow("video", frame);
    		if (waitKey(20) == 27)//27是键盘摁下esc时,计算机接收到的ascii码值
    		{
    			break;
    		}
    	}
        }
    

    后续我会给出目前比较流行的使用opencv实现人脸识别的具体实现。以上。

  • 相关阅读:
    hdu 2200 Eddy's AC难题(简单数学。。)
    hdu 2201 熊猫阿波的故事(简单概率。。)
    hdu 2571 命运(水DP)
    hdu 2955 Robberies(背包DP)
    GDI+图形图像技术1
    C#笔记2__Char类、String类、StringBuilder类 / 正则表达式 /
    C#笔记1__命名空间 / 常量 / object / is、as、...?... :...
    VS2013快捷键及技巧 / 智能插件
    JAVA笔记15__TCP服务端、客户端程序 / ECHO程序 /
    JAVA笔记14__多线程共享数据(同步)/ 线程死锁 / 生产者与消费者应用案例 / 线程池
  • 原文地址:https://www.cnblogs.com/duye/p/8641106.html
Copyright © 2020-2023  润新知