写在前面的话:

  1. 版权声明:本文为博主原创文章,转载请注明出处!
  2. 博主是一个小菜鸟,并且非常玻璃心!如果文中有什么问题,请友好地指出来,博主查证后会进行更正,啾咪~~
  3. 每篇文章都是博主现阶段的理解,如果理解的更深入的话,博主会不定时更新文章。
  4. 本文初次更新时间:2020.12.04,最后更新时间:2020.12.04

正文开始

1. vector

此部分为C++预备知识,比较熟练可忽略本部分内容。

1.1 vector简介

向量(Vector)是一个封装了动态大小数组的顺序容器(Sequence Container),它能存放各种类型的对象。可以简单的认为vector是一个能够存放任意类型的动态数组

使用vector时需要引入:

#include <vector>

using namespace std;

1.2 vector示范

下面的语句,相当于声明了一个int数组,没有指定大小,可以动态添加或删除元素:

vector<int> v;  //声明一个 int 向量 v,未分配大小

2. Vec3b

2.1 定义

Vec3b可以看作是vector<uchar, 3>,即一个uchar类型、长度为3的vector向量。

简单来说,Vec3b就是一个uchar类型的数组,长度为 3。

例如:

Vec3b color;  //变量 color 是一个长度为 3 的 uchar 数组,用于描述 RGB 颜色

//在 OpenCV 中,颜色为 BGR,而不是 RGB
color[0] = 255;    // 0 是 B 通道,该句修改 B 通道数据
color[1] = 255;    // 1 是 G 通道,该句修改 G 通道数据
color[2] = 255;    // 2 是 R 通道,该句修改 R 通道数据

2.2 读取像素

由于在OpenCV中,使用imread读取到的Mat图像数据,都是用uchar类型的数据存储,对于RGB三通道的图像,每个点的数据都是一个Vec3b类型的数据。

使用at定位方法如下:

Mat mat = imread("test.jpg");

//(row, col)即所需要定位点的坐标
mat.at<Vec3b>(row, col)[0] = 255;  //修改点 (row, col) 的 B 通道数据
mat.at<Vec3b>(row, col)[1] = 255;  //修改点 (row, col) 的 G 通道数据
mat.at<Vec3b>(row, col)[2] = 255;  //修改点 (row, col) 的 R 通道数据

再如下例,返回值为<>中的类型:

Mat mat;

mat.at<uchar>(row, col);    //单通道,返回一个 uchar 类型值
mat.at<Vec3b>(row, col);    //三通道,返回 <Vec3b>,即返回一个 uchar 数组,长度为 3
mat.at<Vec4b>(row, col);    //四通道

需要注意的是,上例中返回的都是uchar类型,直接使用cout输出为字符格式,需要强制转换为int类型之后输出:

Vec3b bgr = frame.at<Vec3b>(i, j);

printf("b = %d, g = %d, r = %d\n", bgr[0], bgr[1], bgr[2]);
//或
cout << (int)bgr[0] << ", " << (int)bgr.val[1] << ", " << (int)bgr.val[2] << endl;

2.3 使用

从摄像头中抓取一帧,并读取图像像素值:

#include "opencv2/core.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
#include <iostream>

using namespace cv;
using namespace std;

int main()
{
    VideoCapture capture;
    capture.open(0);  //读入默认摄像头
    if (!capture.isOpened()) {
        cout << "video not open.\n";
        return -1;
    }

    Mat frame;
    capture >> frame;  //读一帧
    if (frame.empty()) {
        cout << "get frame error.\n";
        return -1;
    }

    //遍历该图像每一个像素,并输出 BGR 值
    for (int i = 0; i < frame.rows; i++) {
        for (int j = 0; j < frame.cols; j++) {
            Vec3b bgr = frame.at<Vec3b>(i, j);
            printf("b = %d, g = %d, r = %d\n", bgr[0], bgr[1], bgr[2]);
        }
    }

    return 0;
}

参考

OpenCV Vec3b类型的含义与使用
Opencv之是什么东东
opencv 中图像像素的读取与显示

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐