• opencv中的图像操作


    图像操作

    输入输出

    从文件中加载图像:

     Mat img = imread(filename); 
    
     // 读取灰度图
     Mat img = imread(filename, IMREAD_GRAYSCALE);
    

    保存图像

    imwrite(filename,img);
    

    文件的格式由其扩展名决定。
    使用cv::imdecodecv::imencode从/到内存读取和写入图像,而不是文件。

    图像的基本操作

    访问像素的强度值

    对于单通道图像,如灰度图,每个像素只有一个强度值,可以直接使用**at**来获取。

     Scalar intensity = img.at<uchar>(y, x);
    

    对于多通道图像,通常指三通道BGR色彩图像,则需要使用Vec3b

     Vec3b intensity = img.at<Vec3b>(y, x);
     uchar blue = intensity.val[0];
     uchar green = intensity.val[1];
     uchar red = intensity.val[2];
    

    此外,仅在C++中可以使用std::vector来构造一个矩阵。

     vector<Point2f> points;
     //... fill the array
     Mat pointsMat = Mat(points);
    

    C++还可以使用同样的方法:

     Point2f point = pointsMat.at<Point2f>(i, 0);
    

    内存管理和引用计数

    Mat是一个保持矩阵/图像特征(行和列数,数据类型等)和指向数据的指针的结构。也因此,我们其实可以有多个关联到同一个数据的Mat实例。当Mat的一个特定实例被销毁时,Mat会保持一个引用计数,该计数告诉我们数据是否必须被释放。

    以下是一个没有拷贝数据创造两个Mat的例子:

     std::vector<Point3f> points;
     // .. fill the array
     Mat pointsMat = Mat(points).reshape(1);
     // 该方法通常用来处理大量点数据并将其转换成矩阵
    

    结果是我们将会获得一个32FC1(32-bit浮点单通道,其列数为3)的三通道矩阵,而不是32FC3的单通道矩阵。pointsMat使用来自点的数据且不会再销毁时释放内存。但是,在实际的例子中,开发者仍然需要确保points的生命周期比pointsMat更长。如果需要拷贝数据,请使用cv::Mat::copyTocv::Mat::clone来进行复制操作。

     Mat img = imread("image.jpg");
     Mat img1 = img.clone();
    

    可以为每个函数提供一个空输出Mat。每个实现都为目标矩阵调用Mat::create。如果矩阵为空,则此方法为其分配数据。如果它不为空并且具有正确的大小和类型,则该方法不执行任何操作。但是,如果大小或类型与输入参数不同,则释放(并丢失)旧数据并分配新数据。举个例子:

     Mat img = imread("image.jpg");
     Mat sobelx;
     Sobel(img, sobelx, CV_32F, 1, 0);
    

    基础操作

     // 从一个已经存在的灰度图中获取一个黑色的图像
     img = Scalar(0); 
     
     // 选取ROI(region of interest)
     Rect r(10, 10, 100, 100);
     Mat smallImg = img(r);
    
     // 从彩色图转换成灰度图
     Mat img = imread("image.jpg"); // loading a 8UC3 image
     Mat grey;
     cvtColor(img, grey, COLOR_BGR2GRAY);
    
     // 将图片从8UC1转换到32FC1
     src.convertTo(dst, CV_32F);
    

    图像可视化

    在开发过程中,能看到你算法的中间结果是非常有帮助的。Opencv提供了一种非常好用的可视化图像的方法。一个8U的图像可以被如下展示:

     Mat img = imread("image.jpg");
     namedWindow("image", WINDOW_AUTOSIZE);
     imshow("image", img);
     waitKey();
    

    waitKey的调用将会形成一个消息传递循环,等待“图像”窗口中的按键才会被中止。一个32F的图像需要被转换成8U的类型,例子如下所示:

     Mat img = imread("image.jpg");
     Mat grey;
     cvtColor(img, grey, COLOR_BGR2GRAY);
     Mat sobelx;
     Sobel(grey, sobelx, CV_32F, 1, 0);
     double minVal, maxVal;
     minMaxLoc(sobelx, &minVal, &maxVal); //find minimum and maximum intensities
     Mat draw;
     sobelx.convertTo(draw, CV_8U, 255.0/(maxVal - minVal), -minVal * 255.0/(maxVal - minVal));
     namedWindow("image", WINDOW_AUTOSIZE);
     imshow("image", draw);
     waitKey();
    

    这里cv::namedWindow不是必需的,因为它后面紧跟着cv::imshow。然而,它可以用来改变窗口属性或当使用cv::createTrackbar

  • 相关阅读:
    nuxt3打包后请求页面不渲染
    java Collections工具类
    spark算子讲解
    redux-获取导航标题案例(+react-intl 国际化)
    WPF 控件专题 GridSplitter详解
    通过两个stack来实现Queue
    实验: GVRP 配置,三层交换机通讯 ,VLAN 间路由,单臂路由与路由器子接口的配置,vlan-单臂路由技术
    英诺伟再冲刺港交所上市:上半年利润下降77%,严航为董事长兼CEO
    C/C++内存管理
    【C/C++】BMP格式32位转24位
  • 原文地址:https://blog.csdn.net/weixin_45591821/article/details/139652326