【学习OpenCV4】如何操作图像中的像素?
像素的操作
- 一、读写操作
- 1.1 数组遍历
- 1.2 指针遍历
- 二、算术操作
- 2.1 像素的
- 2.2 图像算术操作API
- 三、逻辑操作
- 3.1 基本知识—真值表
- 3.2 画个矩形
- 3.3 逻辑运算
一、读写操作
1.1 数组遍历
由于图像本质就是Mat矩阵,因此要读写像素点,可以采用数组遍历的方式访问Mat矩阵内的每一个元素。但我们要注意,灰度图和彩色图的通道数是不一样的,灰度图是单通道的,彩色图是三通道的。因此读写像素点就分为了读写灰度图像素和读写彩色图像素两种情况。
① 读写灰度图像素
灰度图内每一个像素点对应Mat矩阵的一个值,因此访问灰度图的像素就相当于访问Mat矩阵的元素。其语法如下
//读灰度图像素
int pv = image.at<uchar>(row, col);
//写灰度图像素(反转颜色)
image.at<uchar>(row, col) = 255 - pv;
其中由于每个灰度图像素为1个字节(0-255),因此使用uchar。其中的row代表Mat矩阵行数,col代表列数。
② 读写彩色图像
彩色图像中每个像素点对应Mat矩阵的三个值,访问方式类似灰度图像。
//读彩色图像素
Vec3b bgr = image.at<Vec3b>(row, col);
//写彩色图像素(反转颜色)
image.at<Vec3b>(row, col)[0] = 255 - bgr[0];
image.at<Vec3b>(row, col)[1] = 255 - bgr[1];
image.at<Vec3b>(row, col)[2] = 255 - bgr[2];
由于访问彩色图像素点需要一次性读取三个值,因此我们使用了Vec3b这个结构(可以看成一个数组),可以直接将访问得到的三个值存储在Vec3b这个结构定义的变量中。
如果彩色像素点的值是整型,需要用Vec3i;如果是浮点数类型,需要用vec3f。
③ 示例程序
void MyDemo::pixelVisit_Demo(Mat& image) {int w = image.cols;int h = image.rows;int dims = image.channels();for (int row = 0; row < h; row++) {for (int col = 0; col < w; col++) {//灰度图像if (dims == 1) {int pv = image.at<uchar>(row, col);image.at<uchar>(row, col) = 255 - pv;}//彩色图像if (dims == 3) {Vec3b bgr = image.at<Vec3b>(row, col);image.at<Vec3b>(row, col)[0] = 255 - bgr[0];image.at<Vec3b>(row, col)[1] = 255 - bgr[1];image.at<Vec3b>(row, col)[2] = 255 - bgr[2];}}}imshow("Pixel Visit Demo", image);
}
1.2 指针遍历
指针遍历的原理与数组遍历类似。定义一个指针指向当前行的首地址,然后利用此指针即可遍历访问本行所有像素点。
void MyDemo::pixelVisit_Demo(Mat& image) {int w = image.cols;int h = image.rows;int dims = image.channels();for (int row = 0; row < h; row++) {uchar* current_row = image.ptr<uchar>(row);for (int col = 0; col < w; col++) {//灰度图像if (dims == 1) {*current_row++ = 255 - *current_row;}//彩色图像if (dims == 3) {*current_row++ = 255 - *current_row;*current_row++ = 255 - *current_row;*current_row++ = 255 - *current_row;}}}imshow("Pixel Visit Demo", image);
}
其中current_row
随着循环的进行指向每一行的首地址。
*current_row++ = 255 - *current_row;
是指将 current_row 指向的值(灰度图的像素点或彩色图像素点的一个通道)色彩反转,然后令指针+1,使其指向下一个像素或像素的下一个通道。
二、算术操作
2.1 像素的
对一个图像Mat矩阵可以直接进行加减乘除(注意彩色图加法需要Scalar),加减法处理的结果就是增大/减小图像的亮度,乘除法同理,但要注意在处理时可能会使像素值超出(0~255)的范围,可以使用saturate_cast函数进行截断。
//image * m -> dst
void MyDemo::operators_Demo(Mat& image) {Mat m = Mat::zeros(image.size(), image.type());m = Scalar(20, 20, 20);Mat dst = Mat::zeros(image.size(), image.type());int w = image.cols;int h = image.rows;int dims = image.channels();for (int row = 0; row < h; row++) {for (int col = 0; col < w; col++) {//灰度图像if (dims == 1) {int pv = image.at<uchar>(row, col);image.at<uchar>(row, col) = 255 - pv;}//彩色图像if (dims == 3) {Vec3b p1 = image.at<Vec3b>(row, col);Vec3b p2 = m.at<Vec3b>(row, col);dst.at<Vec3b>(row, col)[0] = saturate_cast<uchar>(p1[0] * p2[0]);dst.at<Vec3b>(row, col)[1] = saturate_cast<uchar>(p1[1] * p2[1]);dst.at<Vec3b>(row, col)[2] = saturate_cast<uchar>(p1[2] * p2[2]);}}}imshow("operator",dst);
}
2.2 图像算术操作API
功能 | 函数 |
---|---|
加法 | add(img1, img2, imgout); |
减法 | subtract(img1, img2, imgout); |
乘法 | multiply(img1, img2, imgout); |
除法 | divide(img1, img2, imgout); |
void MyDemo::operators_Demo(Mat& image) {Mat dst = Mat::zeros(image.size(), image.type());Mat m = Mat::zeros(image.size(), image.type());m = Scalar(20, 20, 20);//add(image, m, dst);//subtract(image, m, dst);multiply(image, m, dst);//divide(image, m, dst);imshow("operator",dst);}
三、逻辑操作
3.1 基本知识—真值表
A | B | 与 | 或 | 异或 |
---|---|---|---|---|
0 | 0 | 0 | 0 | 0 |
1 | 0 | 0 | 1 | 1 |
0 | 1 | 0 | 1 | 1 |
1 | 1 | 1 | 1 | 0 |
3.2 画个矩形
为了更直观的显示像素逻辑运算的结果,我们可以画两个矩形,让两个矩形的相交区域进行逻辑运算。
画矩形方法很简单,只需要先创建一个空白图像,然后调用rectangle函数就可以。
rectangle(m1, Rect(50, 50, 80, 80), Scalar(255, 255, 0), -1, LINE_8, 0);
rectangle(被处理图像, 左上点坐标, 颜色, 线宽, 线型, 坐标点的小数点位数);
示例程序如下:
void MyDemo::bitWise_Demo(Mat& image) {Mat m1 = Mat::zeros(Size(256, 256), CV_8UC3);Mat m2 = Mat::zeros(Size(256, 256), CV_8UC3);rectangle(m1, Rect(50, 50, 80, 80), Scalar(255, 255, 0), -1, LINE_8, 0);rectangle(m2, Rect(100, 100, 80, 80), Scalar(0, 255, 255), -1, LINE_8, 0);imshow("m1", m1);imshow("m2", m2);
}
3.3 逻辑运算
运算 | 函数 |
---|---|
与 | bitwise_and(m1, m2, dst); |
或 | bitwise_or(m1, m2, dst); |
非 | bitwise_not(m1, dst); |
异或 | bitwise_xor(m1, m2, dst); |
以“与”操作为例,试验代码如下:
void MyDemo::bitWise_Demo(Mat& image) {Mat m1 = Mat::zeros(Size(256, 256), CV_8UC3);Mat m2 = Mat::zeros(Size(256, 256), CV_8UC3);rectangle(m1, Rect(50, 50, 80, 80), Scalar(255, 255, 0), -1, LINE_8, 0);rectangle(m2, Rect(100, 100, 80, 80), Scalar(0, 255, 255), -1, LINE_8, 0);imshow("m1", m1);imshow("m2", m2);Mat dst;bitwise_and(m1, m2, dst);imshow("bitWise", dst);
}
区域 | 颜色 |
---|---|
背景 | Scalar(0, 0, 0) |
矩形1 | Scalar(255, 255, 0) |
矩形2 | Scalar(0, 255, 255) |
相交区域 | Scalar(0, 255, 0) |
其他区域 | Scalar(0, 0, 0) |
其他的“或”、“非”、“异或”操作类似,有兴趣的可以自己尝试。
【学习OpenCV4】如何操作图像中的像素?相关推荐
- 《OpenCV3编程入门》学习笔记5 Core组件进阶(一)访问图像中的像素
第5章 Core组件进阶 5.1 访问图像中的像素 5.1.1 图像在内存中的存储方式 1.图像矩阵大小取决于通道数,矩阵中的子列个数与通道数相等. 2.如果内存足够大,可以实现连续存储,有助于提升图 ...
- ITK:自定义操作以对应两个图像中的像素
ITK:自定义操作以对应两个图像中的像素 内容提要 输出结果 C++实现代码 内容提要 对两个图像中的相应像素应用预定义的操作. 输出结果 pixel1 was = 2 pixel2 was = 5 ...
- python像素大于_用python处理图片实现图像中的像素访问
前面的一些例子中,我们都是利用Image.open()来打开一幅图像,然后直接对这个PIL对象进行操作.如果只是简单的操作还可以,但是如果操作稍微复杂一些,就比较吃力了.因此,通常我们加载完图片后,都 ...
- python获取图片像素矩阵_用python处理图片实现图像中的像素访问
这篇文章主要介绍了关于用python处理图片实现图像中的像素访问,有着一定的参考价值,现在分享给大家,有需要的朋友可以参考一下 前面的一些例子中,我们都是利用Image.open()来打开一幅图像,然 ...
- OpenCV访问Mat图像中每个像素的值
原文:http://blog.csdn.net/xiaowei_cqu/article/details/7771760 matlab中, a=[1,2,3;4,5,6;7,8,9] a(1,2) 第一 ...
- ITK:预定义操作以对应两个图像中的像素
ITK:预定义操作以对应两个图像中的像素 内容提要 C++实现代码 内容提要 对两个图像中的相应像素应用预定义的操作. C++实现代码 #include "itkImage.h" ...
- 计算机太阳,计算机可以学习在大量太阳图像中查找太阳耀斑和其他事件
一项新的研究表明,计算机可以学习在大量太阳图像中查找太阳耀斑和其他事件,并帮助NOAA预报员及时发出警报.由CIRES和NOAA国家环境信息中心(NCEI)的科学家开发的机器学习技术可以搜索大量卫星数 ...
- 访问图像中每个像素的值
转载请注明出处:http://blog.csdn.net/xiaowei_cqu/article/details/7557063 !!此篇是基于IplImage* (C接口或者说2.1之前版本的接口, ...
- ITK:计算矢量图像中每个像素的大小以生成大小图像
ITK:计算矢量图像中每个像素的大小以生成大小图像 内容提要 输出结果 C++实现代码 内容提要 计算矢量图像中每个像素的大小以生成大小图像 输出结果 C++实现代码 #include "i ...
最新文章
- Mybatis之Oracle增删查改示例--转
- Linux下搭建SVN服务器及自动更新项目文件到web发布目录(www)
- firefox扩展开发(四) : 更多的窗口控件
- 运算放大器基本公式_运算放大器积分器的些微差异
- Linux云服务器安装node.js
- js获取viewbag
- python计算长方体体积最简单代码_python处理DICOM并计算三维模型体积
- 开源WinForms界面开发框架Management Studio 选项卡文档 插件 Office 2007蓝色风格 后台线程...
- C#核编之格式化编程
- springboot2.x整合Email并利用AOP做一个项目异常通知功能
- mirth connect 3.4 添加java到js代码中
- PyKeyBoardFairy可以替代你游戏中的卡键盘和鼠标宏
- java dao 单元测试,你应该如何单元测试DAO层
- 51单片机——串口通信
- 热力图pycharm
- MapReduce强化实验
- php 文字合成图片,PHP图片和文字合成
- 80C51单片机的指令系统
- Cents7 查看当前版本
- 计算机错误651是什么故障,网络连接651错误是什么意思(教你一招解决问题)
热门文章
- poj 3268 bzoj 1631: [Usaco2007 Feb]Cow Party(最短路)
- Matlab 小波变换dwt和wavedec
- samba配置过程(附网络凭据的解决方法)
- Latex除法a/b \frac{a}{b}
- 汇编知识点——数据定义伪指令
- Python Linked List
- button点击事件不响应的解决方法(子视图大小超过父视图)
- 312.	Burst Balloons
- ASP.NET:插件化机制
- #语音信号处理基础(十一)——梅尔倒谱系数的提取