【opencv入门教程】15. 访问像素的十四种方式

news2024/12/24 9:03:30

文章选自:
请添加图片描述

一、像素访问

一张图片由许多个点组成,每个点就是一个像素,每个像素包含不同的值,对图像像素操作是图像处理过程中常使用的

二、访问像素



void Samples::AccessPixels1(Mat &image, int div = 64) {
  int nl = image.rows;                    //行数
  int nc = image.cols * image.channels(); //每行元素的总元素数量

  for (int j = 0; j < nl; j++) {
    uchar *data = image.ptr<uchar>(j);

    for (int i = 0; i < nc; i++) {
      //-------------开始处理每个像素-------------------
      data[i] = data[i] / div * div + div / 2;
      //-------------结束像素处理------------------------
    } //单行处理结束
  }
}

//-----------------------------------【方法二】-------------------------------------------------
//      说明:利用 .ptr 和 * ++
//-------------------------------------------------------------------------------------------------
void Samples::AccessPixels2(Mat &image, int div = 64) {
  int nl = image.rows;                    //行数
  int nc = image.cols * image.channels(); //每行元素的总元素数量

  for (int j = 0; j < nl; j++) {
    uchar *data = image.ptr<uchar>(j);

    for (int i = 0; i < nc; i++) {
      //-------------开始处理每个像素-------------------
      *data++ = *data / div * div + div / 2;
      //-------------结束像素处理------------------------
    } //单行处理结束
  }
}

//-----------------------------------------【方法三】-------------------------------------------
//      说明:利用.ptr 和 * ++ 以及模操作
//-------------------------------------------------------------------------------------------------
void Samples::AccessPixels3(Mat &image, int div = 64) {
  int nl = image.rows;                    //行数
  int nc = image.cols * image.channels(); //每行元素的总元素数量

  for (int j = 0; j < nl; j++) {
    uchar *data = image.ptr<uchar>(j);

    for (int i = 0; i < nc; i++) {
      //-------------开始处理每个像素-------------------
      int v = *data;
      *data++ = v - v % div + div / 2;
      //-------------结束像素处理------------------------
    } //单行处理结束
  }
}

//----------------------------------------【方法四】---------------------------------------------
//      说明:利用.ptr 和 * ++ 以及位操作
//----------------------------------------------------------------------------------------------------
void Samples::AccessPixels4(Mat &image, int  div = 64) {
  int nl = image.rows;                    //行数
  int nc = image.cols * image.channels(); //每行元素的总元素数量
  int n = static_cast<int>(log(static_cast<double>(div)) / log(2.0));
  //掩码值
  uchar mask = 0xFF << n; // e.g. 对于 div=16, mask= 0xF0

  for (int j = 0; j < nl; j++) {
    uchar *data = image.ptr<uchar>(j);

    for (int i = 0; i < nc; i++) {
      //------------开始处理每个像素-------------------
      *data++ = *data & mask + div / 2;
      //-------------结束像素处理------------------------
    } //单行处理结束
  }
}

//----------------------------------------【方法五】----------------------------------------------
//      说明:利用指针算术运算
//---------------------------------------------------------------------------------------------------
void Samples::AccessPixels5(Mat &image, int  div = 64) {
  int nl = image.rows;                    //行数
  int nc = image.cols * image.channels(); //每行元素的总元素数量
  int n = static_cast<int>(log(static_cast<double>(div)) / log(2.0));
  int step = image.step; //有效宽度
  //掩码值
  uchar mask = 0xFF << n; // e.g. 对于 div=16, mask= 0xF0

  //获取指向图像缓冲区的指针
  uchar *data = image.data;

  for (int j = 0; j < nl; j++) {
    for (int i = 0; i < nc; i++) {
      //-------------开始处理每个像素-------------------
      *(data + i) = *data & mask + div / 2;
      //-------------结束像素处理------------------------
    } //单行处理结束
    data += step; // next line
  }
}

//---------------------------------------【方法六】----------------------------------------------
//      说明:利用 .ptr 和 * ++以及位运算、image.cols * image.channels()
//-------------------------------------------------------------------------------------------------
void Samples::AccessPixels6(Mat &image, int  div = 64) {
  int nl = image.rows; //行数
  int n = static_cast<int>(log(static_cast<double>(div)) / log(2.0));
  //掩码值
  uchar mask = 0xFF << n; // e.g. 例如div=16, mask= 0xF0

  for (int j = 0; j < nl; j++) {
    uchar *data = image.ptr<uchar>(j);

    for (int i = 0; i < image.cols * image.channels(); i++) {
      //-------------开始处理每个像素-------------------
      *data++ = *data & mask + div / 2;
      //-------------结束像素处理------------------------
    } //单行处理结束
  }
}

// -------------------------------------【方法七】----------------------------------------------
//      说明:利用.ptr 和 * ++ 以及位运算(continuous)
//-------------------------------------------------------------------------------------------------
void Samples::AccessPixels7(Mat &image, int  div = 64) {
  int nl = image.rows;                    //行数
  int nc = image.cols * image.channels(); //每行元素的总元素数量

  if (image.isContinuous()) {
    //无填充像素
    nc = nc * nl;
    nl = 1; // 为一维数列
  }

  int n = static_cast<int>(log(static_cast<double>(div)) / log(2.0));
  //掩码值
  uchar mask = 0xFF << n; // e.g. 比如div=16, mask= 0xF0

  for (int j = 0; j < nl; j++) {
    uchar *data = image.ptr<uchar>(j);

    for (int i = 0; i < nc; i++) {
      //-------------开始处理每个像素-------------------
      *data++ = *data & mask + div / 2;
      //-------------结束像素处理------------------------
    } //单行处理结束
  }
}

//------------------------------------【方法八】------------------------------------------------
//      说明:利用 .ptr 和 * ++ 以及位运算 (continuous+channels)
//-------------------------------------------------------------------------------------------------
void Samples::AccessPixels8(Mat &image, int  div = 64) {
  int nl = image.rows; //行数
  int nc = image.cols; //列数

  if (image.isContinuous()) {
    //无填充像素
    nc = nc * nl;
    nl = 1; // 为一维数组
  }

  int n = static_cast<int>(log(static_cast<double>(div)) / log(2.0));
  //掩码值
  uchar mask = 0xFF << n; // e.g. 比如div=16, mask= 0xF0

  for (int j = 0; j < nl; j++) {
    uchar *data = image.ptr<uchar>(j);

    for (int i = 0; i < nc; i++) {
      //-------------开始处理每个像素-------------------
      *data++ = *data & mask + div / 2;
      *data++ = *data & mask + div / 2;
      *data++ = *data & mask + div / 2;
      //-------------结束像素处理------------------------
    } //单行处理结束
  }
}

// -----------------------------------【方法九】 ------------------------------------------------
//      说明:利用Mat_ iterator
//-------------------------------------------------------------------------------------------------
void Samples::AccessPixels9(Mat &image, int  div = 64) {
  //获取迭代器
  Mat_<Vec3b>::iterator it = image.begin<Vec3b>();
  Mat_<Vec3b>::iterator itend = image.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;
    //-------------结束像素处理------------------------
  } //单行处理结束
}

//-------------------------------------【方法十】-----------------------------------------------
//      说明:利用Mat_ iterator以及位运算
//-------------------------------------------------------------------------------------------------
void Samples::AccessPixels10(Mat &image, int  div = 64) {
  // div必须是2的幂
  int n = static_cast<int>(log(static_cast<double>(div)) / log(2.0));
  //掩码值
  uchar mask = 0xFF << n; // e.g. 比如 div=16, mask= 0xF0

  // 获取迭代器
  Mat_<Vec3b>::iterator it = image.begin<Vec3b>();
  Mat_<Vec3b>::iterator itend = image.end<Vec3b>();

  //扫描所有元素
  for (; it != itend; ++it) {
    //-------------开始处理每个像素-------------------
    (*it)[0] = (*it)[0] & mask + div / 2;
    (*it)[1] = (*it)[1] & mask + div / 2;
    (*it)[2] = (*it)[2] & mask + div / 2;
    //-------------结束像素处理------------------------
  } //单行处理结束
}

//------------------------------------【方法十一】---------------------------------------------
//      说明:利用Mat Iterator_
//-------------------------------------------------------------------------------------------------
void Samples::AccessPixels11(Mat &image, int  div = 64) {
  //获取迭代器
  Mat_<Vec3b>           cimage = image;
  Mat_<Vec3b>::iterator it = cimage.begin();
  Mat_<Vec3b>::iterator itend = cimage.end();

  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;
    //-------------结束像素处理------------------------
  }
}

void Samples::AccessPixels12(Mat &image, int  div = 64) {
  int nl = image.rows; //行数
  int nc = image.cols; //列数

  for (int j = 0; j < nl; j++) {
    for (int i = 0; i < nc; i++) {
      //-------------开始处理每个像素-------------------
      image.at<Vec3b>(j, i)[0] = image.at<Vec3b>(j, i)[0] / div * div + div / 2;
      image.at<Vec3b>(j, i)[1] = image.at<Vec3b>(j, i)[1] / div * div + div / 2;
      image.at<Vec3b>(j, i)[2] = image.at<Vec3b>(j, i)[2] / div * div + div / 2;
      //-------------结束像素处理------------------------
    } //单行处理结束
  }
}

//----------------------------------【方法十三】-----------------------------------------------
//      说明:利用图像的输入与输出
//-------------------------------------------------------------------------------------------------
void Samples::AccessPixels13(const Mat &image,  //输入图像
  Mat &      result, // 输出图像
  int         div = 64) {

  int nl = image.rows; //行数
  int nc = image.cols; //列数

  //准备好初始化后的Mat给输出图像
  result.create(image.rows, image.cols, image.type());

  //创建无像素填充的图像
  nc = nc * nl;
  nl = 1; //单维数组

  int n = static_cast<int>(log(static_cast<double>(div)) / log(2.0));
  //掩码值
  uchar mask = 0xFF << n; // e.g.比如div=16, mask= 0xF0

  for (int j = 0; j < nl; j++) {
    uchar *      data = result.ptr<uchar>(j);
    const uchar *idata = image.ptr<uchar>(j);

    for (int i = 0; i < nc; i++) {
      //-------------开始处理每个像素-------------------
      *data++ = (*idata++) & mask + div / 2;
      *data++ = (*idata++) & mask + div / 2;
      *data++ = (*idata++) & mask + div / 2;
      //-------------结束像素处理------------------------
    } //单行处理结束
  }
}

//--------------------------------------【方法十四】-------------------------------------------
//      说明:利用操作符重载
//-------------------------------------------------------------------------------------------------
void Samples::AccessPixels14(Mat &image, int div = 64) {
  int n = static_cast<int>(log(static_cast<double>(div)) / log(2.0));
  //掩码值
  uchar mask = 0xFF << n; // e.g. 比如div=16, mask= 0xF0

  //进行色彩还原
  image = (image & Scalar(mask, mask, mask)) + Scalar(div / 2, div / 2, div / 2);
}


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2255611.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Ansys Maxwell使用技巧

1、回到原点 点击Fit All 2、长方体做差 选中两个长方体&#xff0c; 点击Subtracct&#xff0c;就可以得到一个镂空的绕组。 3、电感仿真步骤 3.1 画磁芯 3.2 画绕组 3.3 加激励 选择截面积-右键绕组-Edit-Surface-Section-YZ 选择一个截面添加电流激励 3.4选材料 绕组一…

掌握谈判技巧,达成双赢协议

在当今竞争激烈且合作频繁的社会环境中&#xff0c;谈判成为了我们解决分歧、谋求共同发展的重要手段。无论是商业合作、职场交流&#xff0c;还是国际事务协商&#xff0c;掌握谈判技巧以达成双赢协议都具有极其关键的意义。它不仅能够让各方在利益分配上找到平衡点&#xff0…

MacOS 命令行详解使用教程

本章讲述MacOs命令行详解的使用教程&#xff0c;感谢大家观看。 本人博客:如烟花般绚烂却又稍纵即逝的主页 MacOs命令行前言&#xff1a; 在 macOS 上,Terminal&#xff08;终端) 是一个功能强大的工具&#xff0c;它允许用户通过命令行直接与系统交互。本教程将详细介绍 macOS…

第十七章 使用 MariaDB 数据库管理系统

1. 数据库管理系统 数据库是指按照某些特定结构来存储数据资料的数据仓库。在当今这个大数据技术迅速崛起的年代&#xff0c;互联网上每天都会生成海量的数据信息&#xff0c;数据库技术也从最初只能存储简单的表格数据的单一集中存储模式&#xff0c;发展到了现如今存储海量…

11.17【大数据】Hadoop【DEBUG】

列出hdfs文件系统所有的目录和文件 主节点上 子结点 是一样的 *为什么能登进 slave 02 的主机,但是 master 当中依然显示 slave 02 为 DeadNode?* hadoop坏死节点的重启_hadoop3 子节点重启-CSDN博客 注意hadoop-daemon.sh 实际上位于 Hadoop 的 sbin 目录中&#xff0c;而不…

MetaGPT 安装

1. 创建环境 conda create -n metagpt python3.10 && conda activate metagpt2. 可编辑方式安装 git clone --depth 1 https://github.com/geekan/MetaGPT.git cd MetaGPT pip install -e .3. 配置 metagpt --init-config运行命令&#xff0c;在C盘位置C:\Users\325…

图的最小生成树(Kruskal算法,Prim算法)

无向图中的最短路径问题&#xff1f;No&#xff0c;最短路径不是最小生成树&#xff01; 什么是最小生成树&#xff1f; 在一个无向连通图中&#xff0c;有一个子图连接所有顶点&#xff0c;并且权重和最小&#xff0c;那么他就是最小生成树。如果权重和不是最小的只能叫做生…

【Flink-scala】DataStream编程模型之水位线

DataStream API编程模型 1.【Flink-Scala】DataStream编程模型之 数据源、数据转换、数据输出 2.【Flink-scala】DataStream编程模型之 窗口的划分-时间概念-窗口计算程序 3.【Flink-scala】DataStream编程模型之 窗口计算-触发器-驱逐器 文章目录 DataStream API编程模型前言…

PHP RabbitMQ连接超时问题

问题背景 Error: The connection timed out after 3 sec while awaiting incoming data 看到这个报错&#xff0c;我不以为意&#xff0c;认为是我设置的超时时间不够导致的&#xff0c;那就设置长一点 Error: The connection timed out after 300 sec while awaiting incom…

【LeetCode热题100】BFS解决FloodFill算法

这篇博客主要记录了使用BFS解决FloodFill算法的几道题目&#xff0c;包括图像渲染、岛屿数量、岛屿的最大面积、被包围的区域。 class Solution {using PII pair<int, int>; public:vector<vector<int>> floodFill(vector<vector<int>>& im…

L2G3000-LMDeploy 量化部署实践

文章目录 LMDeploy 量化部署实践闯关任务环境配置W4A16 量化 KV cacheKV cache 量化Function call LMDeploy 量化部署实践闯关任务 环境配置 conda create -n lmdeploy python3.10 -y conda activate lmdeploy conda install pytorch2.1.2 torchvision0.16.2 torchaudio2.1.…

大数据新视界 -- 大数据大厂之 Hive 临时表与视图:灵活数据处理的技巧(上)(29 / 30)

&#x1f496;&#x1f496;&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎你们来到 青云交的博客&#xff01;能与你们在此邂逅&#xff0c;我满心欢喜&#xff0c;深感无比荣幸。在这个瞬息万变的时代&#xff0c;我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…

Ubuntu操作系统在Vmware中的安装、常用操作、最基础的知识、imx6ll基本开发环境配置

01-Ubuntu操作系统的安装 网盘搜索 “ubuntu18.04.zip”&#xff0c;下载下来之后用Vmware打开就行了。 我用的虚拟机是15.5.6&#xff0c;实测没有问题。 启动时用户名为book的密码为123456 提问&#xff1a;Ubuntu与Centos系统有何区别&#xff1f; 详情见 https://blog.cs…

windows2012服务器安装sqlserver2012出现NetFx3错误的解决方法。

出现以下错误: 启用 Windows 功能 NetFx3 时出错&#xff0c;错误代码: -2146498298。请尝试从 Windows 管理工具启用 Windows 功能 NetFx3&#xff0c;然后重新运行安装程序。有关如何启用 Windows 功能的详细信息&#xff0c;具体解决办法如下&#xff1a; 1、打开PowerShel…

FPGA实战篇(按键控制LDE实验)

1.按键简介 按键开关是一种电子开关&#xff0c;属于电子元器件类。我们的开发板上有两种按键开关&#xff1a;第一种是本实验所使用的轻触式按键开关&#xff0c;简称轻触开关。使用时以向开关的操作方向施加压力使内部电路闭合接通&#xff0c;当撤销压力时开关断开&#xff…

C++析构函数和构造函数

一、构造函数 1.构造函数的基本概念 1.对构造函数的理解&#xff1a; 构造函数是类的一种特殊成员函数&#xff0c;其主要功能是在创建对象时进行初始化操作。它的名字与类名相同&#xff0c;并且没有返回值类型&#xff08;不能是void&#xff09;。例如&#xff0c;对于一个…

【Axure高保真原型】数值条件分组

今天和大家分享数值条件分组的原型模板&#xff0c;效果包括&#xff1a; 点击添加分组按钮&#xff0c;可以显示添加弹窗&#xff0c;填写分组名称和数值区间后&#xff0c;可以新增该分组信息‘’ 修改分组区间&#xff0c;可以直接在输入框里修改已有的分组区间&#xff0c…

阳光电脑公司的维修服务微信小程序ssm+论文源码调试讲解

第2章 开发环境与技术 阳光电脑公司的维修服务微信小程序的编码实现需要搭建一定的环境和使用相应的技术&#xff0c;接下来的内容就是对阳光电脑公司的维修服务微信小程序用到的技术和工具进行介绍。 2.1 MYSQL数据库 本课题所开发的应用程序在数据操作方面是不可预知的&…

重生之我在异世界学编程之C语言:深入结构体篇(下)

大家好&#xff0c;这里是小编的博客频道 小编的博客&#xff1a;就爱学编程 很高兴在CSDN这个大家庭与大家相识&#xff0c;希望能在这里与大家共同进步&#xff0c;共同收获更好的自己&#xff01;&#xff01;&#xff01; 本文目录 引言结构体的自引用实现链表一、链表的基…

使用Redis Stream偶发空指针问题

问题描述&#xff1a;使用redission客户端封装的stream消息队列&#xff0c;在进行消息轮询时&#xff0c;偶发出现空指针问题。 [2024-11-13 09:59:20] [] [] [redis-stream-consumer-thread-1 ] [lambda$streamMessageListenerContainer$1] [ERROR] [c.r.c.r.s.config.Redi…