2.3 OpenCV对图像的基本操作

操作图片

输入输出

加载图片文件

    Mat img = imread(filename);

如果读取的文件是jpg格式的文件,那么默认就会为此文件创建一个3通道的图像.如果你仅仅是加载一个灰度图像可使用:

    Mat img = imread(filename, IMREAD_GRAYSCALE);

注意
图片的文件格式由图片文件的文件头决定即图片文件的前几个字节所决定,也可以理解为文件的扩展名.保存文件.

    imwrite(filename, img);

使用cv::imdecode和cv::imencode是从内存读写图片,而非从文件进行读写图片.

图片的基本操作

访问像素的值

为了得到像素的值,你首先必须知道图像的类型以及颜色通道的数量.下面是一个单通道的灰度图像(类型是8UC1)访问坐标的例子

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

intensity.val[0]的值的范围是0-255.需要注意下x,y的顺序.因为在OpenCV中,图像用和矩阵相同的结构来表示,所以我们对这两种情况都使用相同的约定--行(y)索引[从0开始]在前,列(x)索引[从0开始]在后.另外你可以使用下面的C符号

  //typedef Scalar_<double> cv::Scalar
  Scalar intensity = img.at<uchar>(Point(x, y));

现在我们来考虑一个BGR(imread返回的默认格式)颜色排序的3通道图像:

    //typedef Vec<double, 3> cv::Vec3d
    Vec3b intensity = img.at<Vec3b>(y, x);
    uchar blue = intensity.val[0];
    uchar green = intensity.val[1];
    uchar red = intensity.val[2];

你可以对浮点图像使用相同的方法(例如你可在3通道的图像上运行Sobel得到图像)

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

同样的方法也可用来改变像素的值

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

OpenCV中有一些函数,特别是calib3d模块的函数,例如cv::projectPoints,它们以Mat的形式接受2D或3D的点阵数组.矩阵应该有确定的列,且每行对应一个点,矩阵的类型应该是32FC2,32FC3,这样的矩阵可以容易的由std::vector构造

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

使用同样的Mat::at()方法可以用来访问矩阵中的每一个点.

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

内存管理和引用计数

Mat是一个用于保存矩阵/图像特征(行,列,数据类型)和数据指针的结构体.所以没有什么可以阻止我们有有多个描述同一个图像的Mat实例.Mat还保持了一个引用计数,此引用计数告诉我们当Mat的一个特定实例被销毁的时候是否需要重新分配数据.下面是创建两个矩阵而不是复制两份数据的例子

    //typedef Point3_<float> cv::Point3f
    std::vector<Point3f> points;
        // .. fill the array
    Mat pointsMat = Mat(points).reshape(1);

上述代码我们得到一个32FC1的3列矩阵,而非一个32FC3的一列矩阵.pointsMat使用来自point的数据,并且在销毁时不会释放内存.在这个特定例子中,开放者必须确保points的声明周期要比pointsMat的声明周期更长.如果我们需要赋值数据的时候可以使用cv::Mat::copyTo()或者cv::Mat::clone():

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

和C API相反在C API中开发者必须创建一个输出图像,并为每个函数提供一个空的输出Mat.C++ API的每个实现均调用Mat::create()来创建目标矩阵.如果矩阵为空,则create()为其分配数据,如果不为空,并且矩阵拥有正确的大小和类型,则此方法不执行任何操作.但是如果size或type和输入参数不同,则释放数据,并重新分配新的数据.

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

基本操作

在矩阵上还定义了许多方便的运算符.

从现有的灰度图生成黑色图

  img = Scalar(0);

设置ROI感兴趣区域

   Rect r(10, 10, 100, 100);
    Mat smallImg = img(r);

Mat转换为C数据结构

    Mat img = imread("image.jpg");
    IplImage img1 = cvIplImage(img);
    CvMat m = cvMat(img);

需要注意的是转换操作也并未复制数据

彩转灰

    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()启动一个消息传递周期,等待"image"窗口中的按键操作,一个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::namedWidow()不是必须的,因为后面紧跟着cv::imshow().当然它可用来改变窗口属性,或使用cv::createTrackBar.


备注:本来以为凭着几年的软件开发经验可以搞下OpenCV了,但是实践看来虽然代码都看得懂.但是深层的原理还是不甚了解呀.有时间还是需要重新找补下丢下的线性代数和高等数学方面的知识了.

优秀的个人博客,低调大师

微信关注我们

原文链接:https://my.oschina.net/u/4026445/blog/4945233

转载内容版权归作者及来源网站所有!

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。

相关文章

发表评论

资源下载

更多资源
优质分享Android(本站安卓app)

优质分享Android(本站安卓app)

近一个月的开发和优化,本站点的第一个app全新上线。该app采用极致压缩,本体才4.36MB。系统里面做了大量数据访问、缓存优化。方便用户在手机上查看文章。后续会推出HarmonyOS的适配版本。

Apache Tomcat7、8、9(Java Web服务器)

Apache Tomcat7、8、9(Java Web服务器)

Tomcat是Apache 软件基金会(Apache Software Foundation)的Jakarta 项目中的一个核心项目,由Apache、Sun 和其他一些公司及个人共同开发而成。因为Tomcat 技术先进、性能稳定,而且免费,因而深受Java 爱好者的喜爱并得到了部分软件开发商的认可,成为目前比较流行的Web 应用服务器。

Java Development Kit(Java开发工具)

Java Development Kit(Java开发工具)

JDK是 Java 语言的软件开发工具包,主要用于移动设备、嵌入式设备上的java应用程序。JDK是整个java开发的核心,它包含了JAVA的运行环境(JVM+Java系统类库)和JAVA工具。

Sublime Text 一个代码编辑器

Sublime Text 一个代码编辑器

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。