当前位置: 首页 > news >正文

OpenCV之像素操作

我们首先了解一下什么是像素,计算机中是如何存储图像,以及opencv是如何表示图像的。

像素

像素是指由图像的小方格即所谓的像素(pixel)组成的,这些小方块都有一个明确的位置和被分配的色彩数值,而这些一小方格的颜色和位置就决定该图像所呈现出来的样子。可以将像素视为整个图像中不可分割的单位或者是元素,不可分割的意思是它不能够再切割成更小单位抑或是元素,它是以一个单一颜色的小格存在。每一个点阵图像包含了一定量的像素,这些像素决定图像在屏幕上所呈现的大小

计算机存储图像:

图像文件存储的都是每一个像素对应的颜色值。

1、位图文件有两种存储像素数据的格式。16777216色(真彩色)的图像,一个像素的颜色可以用24位数据表示。256色的图像可以用调色板对颜色的信息进行编码,一个像素的值对应的是调色板的索引,而不是直接对应一个像素的颜色,调色板的索引映射为像素的颜色。

2、以一百万个像素,256种颜色的BMP文件在电脑上的存储为例。这个文件包括一个十四字节的文件首部,一个四十字节的信息首部,一个1024字节的颜色表,一兆字节的位图数据。文件首部的前两个字节由字符BM组成,还包括了文件长度和位图数据在文件中的起始位置。

3、文件的信息首部包含了图像的高、宽、颜色数等非图形数据。

这个图像共有一百万个像素,一个像素需要八位的颜色信息,文件的这一部分的长度是一百万个字节,字节排放的顺序是自左到右从图像的最下面那行开始,这个文件的总大小是1001078字节。

opencv表示图像:

opencv中很多数据结构为了达到內存使用的最优化,通常都会用它最小上限的空间来分配变量,有的数据结构也会因为图像文件格式的关系而给予适当的变量,因此需要知道它们声明的空间大小来配置适当的变量。一

般标准的图片,为RGB格式它们的大小为8bits格式,范围为0~255,对一个int空间的类型来说实在是太小,整整浪费了24bits的空间,假设有个640*480的BMP文件空间存储內存,那整整浪费了640*480*3*(32-8)bits的內存空间,总共浪费了2.6MB!,也就是那
2.6MB内什么东西都没存储,如果今天以8bits的格式来存储则只使用到0.6MB的內存而已(640*480*3*(8)+54
bits),因此,对于文件格式的对应是一件很重要的事.。

访问像素的三种方法:

  1. 指针访问
  2. 迭代器iterator
  3. 动态地址计算

首先我们来看一段代码:

#include<opencv2/opencv.hpp>
#include<iostream>
using namespace std;
using namespace cv;
//指针操作访问像素
void colorReduce(Mat& img,int div=64)
{int nl = img.rows;int nc = img.cols*img.channels();for(int i = 0;i < nl;i++){uchar* data = img.ptr<uchar>(i);for(int j = 0 ; j < nc;j++){data[j] = data[j]/div*div + div/2;}}}
//迭代器模式
void ColorReduce(Mat& img,int div = 64)
{Mat_<Vec3b>::iterator it = img.begin<Vec3b>();Mat_<Vec3b>::iterator itend = img.end<Vec3b>();for (; it != itend; it++){(*it)[0] = (*it)[0] / div * div + div / 2;(*it)[1] = (*it)[1] / div * div + div / 2;(*it)[2] = (*it)[2] / div * div + div / 2;}namedWindow("dst");imshow("dst", img);
}
//动态地址计算
void colorReduce2(Mat& img,int div = 64)
{int cols = img.cols;int rows = img.rows;for(int i= 0;i < rows;i++){for(int j=0; j < cols;j++){img.at<Vec3b>(i,j)[0] = img.at<Vec3b>(i,j)[0] / div * div +div /2;img.at<Vec3b>(i,j)[1] = img.at<Vec3b>(i,j)[1] / div * div +div /2;img.at<Vec3b>(i,j)[2] = img.at<Vec3b>(i,j)[2] / div * div +div /2;}}
}int main(int argc,char** argv)
{Mat image = imread(argv[1]);imshow("input",image);colorReduce2(image,64);imshow("dst",image);waitKey(0);destroyAllWindows();return 0;
}

指针操作:

//指针操作访问像素
void colorReduce(Mat& img,int div=64)
{int nl = img.rows; // 行数int nc = img.cols*img.channels();//列数x通道数 = 每一行像素的个数for(int i = 0;i < nl;i++){//Mat类提供了ptr函数可以得到任意行的首地址,ptr是一个模板函数uchar* data = img.ptr<uchar>(i); //获取第i行的首地址for(int j = 0 ; j < nc;j++){data[j] = data[j]/div*div + div/2;}}}

迭代器操作:

//迭代器模式
void ColorReduce(Mat& img,int div = 64)
{Mat_<Vec3b>::iterator it = img.begin<Vec3b>();Mat_<Vec3b>::iterator itend = img.end<Vec3b>();for (; it != itend; it++){(*it)[0] = (*it)[0] / div * div + div / 2;(*it)[1] = (*it)[1] / div * div + div / 2;(*it)[2] = (*it)[2] / div * div + div / 2;}namedWindow("dst");imshow("dst", img);
}

如果不熟悉迭代器模式,可以阅读与STL中迭代器相关的资料。

动态地址计算:

//动态地址计算
void colorReduce2(Mat& img,int div = 64)
{int cols = img.cols; //列数int rows = img.rows; //行数for(int i= 0;i < rows;i++){for(int j=0; j < cols;j++){  //处理B蓝色通道img.at<Vec3b>(i,j)[0] = img.at<Vec3b>(i,j)[0] / div * div +div /2;//处理G绿色通道img.at<Vec3b>(i,j)[1] = img.at<Vec3b>(i,j)[1] / div * div +div /2;//处理R红色通道img.at<Vec3b>(i,j)[2] = img.at<Vec3b>(i,j)[2] / div * div +div /2;}}
}

对于彩色图像,每个像素由三个部分:蓝色通道,绿色通道,红色通道(BGR)。因此对于一个包含彩色图像的Mat,会返回一个8位数组组成的向量。OpenCV将此向量定义为Vec3b,即由usigned char 组成的向量。其访问像素通用表达式为:

image.at<Vec3b>(row,col)[channel] = value;

其中索引值表示通道。

这就是访问像素的三种方法,我们看一下效果:

http://www.lryc.cn/news/267092.html

相关文章:

  • Transfer Learning(迁移学习)
  • NPM 的使用技巧:简化 JavaScript 开发和依赖管理
  • 统计和绘图软件GraphPad Prism mac功能特点
  • WWW 指南-万维网联盟(World Wide Web)
  • Linux网络编程之TCP/IP实现高并发网络服务器设计指南
  • 【SpringBoot实战】基于阿里云实现文件上传
  • 大数据技术学习笔记(十一)—— Flume
  • 电路设计时,继电器线圈、风扇电机绕组等感性负载必须有续流二极管。
  • Mongodb基础介绍与应用场景
  • mysql参数配置binlog
  • pytorch常用的几个函数详解
  • Linux下安装Flume
  • 20231225使用BLE-AnalyzerPro WCH升级版BLE-PRO蓝牙分析仪抓取BLE广播数据
  • .net6使用Sejil可视化日志
  • mysql(51) : 大数据导出为insert
  • MFC查找错误的方法
  • Jave EE 网络原理之网络层与数据链路层
  • ElasticSearch 使用映射定义索引结构
  • HTML---网页布局
  • python 普通存款(单利)计算公式:
  • 什么是 PHP 内存溢出 ?遇到了要如何解决呢 ?
  • 本地使用 docker 运行OpenSearch + Dashboard + IK 分词插件
  • 【JavaEE初阶一】线程的概念与简单创建
  • 三叠云工程劳务管理,优化建筑施工管理,提升效率与质量
  • RocketMQ连接报错RemotingConnectException: connect to <192.168.57.129:9876>解决
  • 设计模式--桥接模式
  • redis基本用法学习(C#调用StackExchange.Redis操作redis)
  • 单挑力扣(LeetCode)SQL题:1308. 不同性别每日分数总计
  • Vue3组合式-依赖注入provideinject
  • SRE 与 DevOps 的不同之处