详解OpenCV图像的概念和基本操作

作者:C君莫笑 时间:2021-07-22 02:05:30 

前言:

opencv最主要的的功能是用于图像处理,所以图像的概念贯穿了整个opencv,与其相关的核心类就是Mat。

像素:

图片尺寸以像素为单位时,每一厘米等于28像素,如1515厘米长度的图片,等于420420像素的长度。一个像素所能表达的不同颜色数取决于比特每像素(BPP)。

灰度图像:8bpp=2的8次方=256色,
高彩色:16bpp=2的16次方=65536色,
真彩色:24bpps=2的24次方=16777216色。

图像分辨率:

图像分辨率是图像总像素的多少,由于图像通常用矩阵表示,所以分辨率常用,mn表示,注意: n 表示行数(代表一列包含的像素),m表示列数代表一行包含的像素。

640X480表示图像的长和宽分别为640和480,总像素为640X480=307200(相机中所说的30万分辨率),
800X600表示图像的长和宽分别为800和600,总像素为800X600=480000(相机中所说的50万分辨率)。

图像和矩阵

图像是由像素组成的,而像素实际上就是带有坐标位置和颜色信息的点。我们把图片想象成由若干行,若干列的点组成的, 现实中有RGB颜色系统,我们可以把图中任意一点(位置在第m行,第n列)的点A表示为

A[m,n] = [blue,green,red]
参数解读
m |A点在图像中的第m行
n |A点在图像中的第n列
blue |表示蓝色,三原色(RGB)的第一个数值
green|表示绿色,三原色(RGB)的第二个数值
red |表示红色,三原色(RGB)的第一个数值

每个点对应的亮度可以理解为rgb的值,无符号8位数3维,则一个像素点为3维数组,分别对应RGB的值,在OpenCV中数据类型为:cV_8u3C。
假设Mx N,lij表示第j行j列,对应上图就是M= 300,N= 200。
假设Mx N,lij表示第j行j列,对应上图就是M= 300,N= 200。

详解OpenCV图像的概念和基本操作

注意:在Opencv中三维数组存储RGB值,存储颜色通道的顺序不是RGB,而是BGR,如下图:

详解OpenCV图像的概念和基本操作

Mat排列方式如下:

详解OpenCV图像的概念和基本操作

像素值的读写

很多时候,我们需要读取某个像素值,或者设置某个像素值;在更多的时候,我们需要对整个图像里的所有像素进行遍历。OpenCV提供了多种方法来实现图像的遍历。
方法一:at 函数


    cv::Mat grayim(600, 800, CV_8UC1);
   // 遍历所有像素,并设置像素值
   for( int i = 0; i < grayim.rows; ++i)
   {
       for( int j = 0; j < grayim.cols; ++j )
       {
            grayim.at<uchar>(i,j) = (i+j)%255;
       }

}
  imshow("grayim",grayim);
   cv::Mat colorim(600, 800, CV_8UC3);
   // 遍历所有像素,并设置像素值
   for( int i = 0; i < colorim.rows; ++i)
   {
       for( int j = 0; j < colorim.cols; ++j )
       {
           cv::Vec3b pixel;
           // 注意:opencv通道顺序,BGR,非RGB
           pixel[0] = i%255;  // Blue
           pixel[1] = j%255;  // Green
           pixel[2] = 0;      // Red
           colorim.at<Vec3b>(i,j) = pixel;
       }
   }
   imshow("colorim",colorim);
   waitKey();

方法一:使用数据指针


cv::Mat grayim(600, 800, CV_8UC1);
   cv::Mat colorim(600, 800, CV_8UC3);
   //遍历所有像素,并设置像素值
   for( int i = 0; i < grayim.rows; ++i)
   {
       //获取第 i 行首像素指针
       uchar * p = grayim.ptr<uchar>(i);
       //对第 i 行的每个像素(byte)操作
       for( int j = 0; j < grayim.cols; ++j )
       p[j] = (i+j)%255;
   }
   //遍历所有像素,并设置像素值
   for( int i = 0; i < colorim.rows; ++i)
   {
       //获取第 i 行首像素指针
       cv::Vec3b * p = colorim.ptr<cv::Vec3b>(i);
       for( int j = 0; j < colorim.cols; ++j )
       {
           p[j][0] = i%255;    //Blue
           p[j][1] = j%255;    //Green
           p[j][2] = 0;        //Red
       }
   }

imshow("grayim",grayim);
    imshow("colorim",colorim);

实验效果

详解OpenCV图像的概念和基本操作

图像局部操作

选择单行/单列
示例:A矩阵的第i行,将这一行的所有元素都乘以2,然后赋值给第j行

A.row(j)= A.row(i)*2;

选择多行/多列
Range是OpencV中新增的类,该类有两个关键变量star和end。Range对象可以用来表示矩阵的多个连续的行或者多个连续的列。其表示的范围为从start到end,包含start。


// 创建一个单位阵
Mat A = Mat::eye(10, 10, CV_32S);
// 提取第 1 到 3 列(不包括 3)
Mat B = A(Range::all(), Range(1, 3));
// 提取B的第 5 至 9 行(不包括 9)
// 其实等价于C = A(Range(5, 9), Range(1, 3))
Mat C = B(Range(5, 9), Range::all());

选择指定区域

图像中提取感兴趣区域(Region of interest)有两种方法:
方法—:使用构造函数


//创建宽度为 320,高度为 240 的 3 通道图像
Mat img(Size(320, 240), CV_8UC3);
//roi 是表示 img 中 Rect(10, 10, 100, 100)区域的对象
Mat roi(img, Rect(10, 10, 100, 100));

方法二:使用括号运算符


Mat roi2 = img(Rect(10, 10, 100, 100));
//当然也可以使用Range对象来定义感兴趣区域,如下:
// 用括号运算符
Mat roi3 = img(Range(10, 100), Range(10, 100));
// 用构造函数
Mat roi4(img, Range(10, 100), Range(10, 100));

取对角线元素

矩阵的对角线元素可以使用cv::Mat就的diag()函数获取:


Mat Mat::diag(int d) const

1.当d=0时,表示取主对角线; 当参数d>0是,表示取主对角线下方的次对线,
2. 当d=1时,表示取主对角线下方,且紧贴主多角线的元素;
3. 当参数d<0时,示取主对角线上方的次对角线。如同row()和col)函数,diag()函数也不进行内存复制操作,其复杂度也是0(1)。

来源:https://blog.csdn.net/qq_34623621/article/details/120653817

标签:OpenCV,图像
0
投稿

猜你喜欢

  • Python浅析迭代器Iterator的使用

    2023-11-07 12:04:25
  • 快速掌握如何使用SQL Server来过滤数据

    2009-01-15 13:27:00
  • C#调用python.exe使用arcpy方式

    2021-03-30 05:41:13
  • 何处安放的Loading

    2011-08-10 19:11:20
  • CSS Expression 的优化

    2009-09-24 13:27:00
  • 优化 MySQL 语句的十个建议

    2012-05-08 07:14:36
  • Python中号称神仙的六个内置函数详解

    2021-02-04 13:41:22
  • Python psutil模块简单使用实例

    2023-08-10 21:15:37
  • 利用Python查看目录中的文件示例详解

    2023-02-06 14:13:28
  • Python WebSocket长连接心跳与短连接的示例

    2022-08-20 04:05:15
  • mysql myisam优化设置

    2010-03-13 16:59:00
  • 详解Python中映射类型的内建函数和工厂函数

    2022-10-15 06:24:55
  • 对python 操作solr索引数据的实例详解

    2023-11-02 16:18:19
  • 初学js者对javascript面向对象的认识分析

    2011-03-16 11:04:00
  • asp HTTP 500错误 常见问题分析

    2011-04-07 10:33:00
  • 如何修改MySQL密码(方法大总结)

    2009-11-18 11:07:00
  • ASP.NET 2.0中Gridview控件高级技巧图文教程

    2007-08-07 15:46:00
  • 页面重构中的组件制作要点

    2009-10-25 13:06:00
  • 编程经验点滴 动态SQL的拼接技巧

    2012-11-30 20:03:58
  • QQ影音正式版官网Banner设计

    2009-03-27 18:46:00
  • asp之家 网络编程 m.aspxhome.com