OpenCV—访问图像中的像素

简介: OpenCV—访问图像中的像素

言: OpenCV3编程入门已经进入第五章 (Core组件进阶) 学习了,后面也越来越多对图像的处理,这一节主要是对像素的认识。

一、访问图形中的像素

1、图像在内存之中的存储方式

图像矩阵的大小取决于所用的颜色模型,也就是说取决于所用的通道数。如下灰度图像:

对于多通道的图像,矩阵中的列会包含多个子列,子列个数与通道数相等。

2、颜色空间缩减

(1)问题提出:对于单通道像素,有256个不同的值,若三通道图像,颜色的存储值就有一千六百万多种。

解决: 如此之多的颜色数值,但是达到同样效果的只占很小一部分。颜色空间缩减(color space reduction)可以大大降低运算复杂度。它的做法:将现有颜色空间值除以某个输入值,以获得较少的颜色数,比如:0-9可以取0,10-19取10,以此类推。

(2)uchar类型的三通道图像,每个通道取值0~255,也就是256x256不同的值。

  • 0~9范围的像素值为0
  • 10~19范围的像素值是10
  • 20~29范围的像素值是20

这样操作,将颜色取值降低为26x26x26种情况。即:Inew=(Iold/10)*10。因为uchar类型的值除以int值,结果仍是char类型,所以求出来的小数也要向下取整。

(3)为了防止处理图像像素时,每一步计算都会花销时间,于是可以把计算好的结果提前存入表table中,这样不需要计算,直接取结果即可。

// 1、遍历图像矩阵的每一个像素
// 2、对像素应用上述公式
int divideWith=10;
uchar table[256];
for(int i=0;i<256;i++){
    table[i]=divideWith*(i/divideWith);//table[i]存放值为i像素减小颜色空间结果
}
//p[j]=table[p[j]];

总结:对于较大的图像,有效的方法是预先计算所有可能的值,然后需要这些值的时候,利用查找表直接赋值即可。

3、LUT函数:Look up table操作

说明:函数原型为:operationsOnArrays:LUT()的函数来进行,用于批量进行图像元素查找、扫描与操作图像。

//首先建立一个Mat型用于查表
Mat lookUpTable(1,256,CV_8U);
uchar* p=lookUpTable.data;
for(int i=0;i<256;i++){
  p[i]=table[i];
}
//然后调用函数(I输入,J输出)
for(int i=0;i<times;i++){
  LUT(I,lookUpTable,J);
}

这个地方书上讲的有点模糊,不是很懂,就去参考其他大佬

(1)对于单通道图像,其像素灰度值为0-255,LUT函数可以将函数的一个灰度值转换成其他灰度值。如:将一张图片0-100的像素的灰度值变成0,101-200的像素变成100,201-255的像素变成255。

(2)对于多通道图像,其内部每一个通道都做这样的映射,这样每一个通道的处理就和单通道差不多了。

(3)LUT函数为:

void LUT(InputArray src,InpitArray lut,OutputArray dst);
  • src: 输入图像(单通道或者3通道)
  • lut: 表示查找表,下面会用具体示例介绍
  • dst: 输出图像

(4)单通道图像处理

#include<opencv2/highgui.hpp>
using namespace cv;
int main()
{
  uchar lutData[256];
  for (int i = 0; i < 256; i++)
  {
    if (i <= 100)
      lutData[i] = 0;
    if (i > 100 && i <= 200)
      lutData[i] = 100;
    if (i > 200)
      lutData[i] = 255;
  }
  Mat lut(1, 256, CV_8UC1);
  Mat a = imread("12.jpg", CV_LOAD_IMAGE_GRAYSCALE),b;
  namedWindow("原灰度图像", CV_WINDOW_AUTOSIZE);
  namedWindow("转灰度图像", CV_WINDOW_AUTOSIZE);
  imshow("原灰度图像", a);
  LUT(a, lut, b);
  imshow("转灰度图像", b);
  waitKey(0);
}

4、计时函数

说明:计时函数:getTickCount()和getTickFrequency()

  • getTickCount()函数返回CPU自某个事件(如启动电脑)以来走过的时钟周期数
  • getTickFrequency()函数返回CPU一秒钟走的时钟周期数,我们就可以以秒为单位对某运算计时。
double time0=static_cast<double>(getTickCount());//记录起始时间
//进行图像处理操作。。。。
time0=((double)getTickCount()-time0)/getTickFrequency();
printf("输出运行时间%f\n",time0);
5、访问图像像素的三类方法

说明:任何图像处理算法,都是从操作每个像素开始的。

提供三种访问每个像素的方法

  • 指针访问:C操作符[ ];
  • 迭代器iterator;
  • 动态地址计算

这三种方法在访问速度上略有差异,在debug模式下,比较明显。程序的目的是减少图像中颜色的数量,比如原来的图像是256种颜色,变成64只需要将原来的颜色除以4再乘以4.

示例程序:主程序中调用colorReduce函数来完成减少颜色的工作。

#include<opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<iostream>
using namespace cv;
using namespace std;
//全局函数声明
void colorReduce(Mat &inputImage, Mat& outputImage, int div);

int main()
{
  Mat srcImage = imread("12.jpg");
  imshow("原始图像",srcImage);
  
  //将原始图的参数规格来创建效果图
  Mat dstImage;
  dstImage.create(srcImage.rows, srcImage.cols, srcImage.type());//效果图的大小、类型和原图片相同

  //记录起始时间
  double time0 = static_cast<double>(getTickCount());

  //调用颜色空间缩减函数
  colorReduce(srcImage, dstImage, 128);

  //计算运行时间并输出
  time0 = ((double)getTickCount() - time0) / getTickFrequency();
  printf("此方法运行时间为:%f\n", time0);
  imshow("效果图",dstImage);
  waitKey(0);
}
(1)用指针访问像素

说明:用指针访问像素发这种方法利用的是C语言操作符[ ],这种方法比较快。

void colorReduce(Mat &inputImage, Mat& outputImage, int div)
{
  //参数准备
  outputImage = inputImage.clone();//复制实参到临时变量
  int rowNumber = outputImage.rows;//行数
  int colNumber = outputImage.cols*outputImage.channels();//列数x通道数=每一行元素的个数
  //双重循环,遍历所有的像素值
  for (int i = 0; i < rowNumber; i++) {//行循环
    uchar* data = outputImage.ptr<uchar>(i);//获取第i行的首地址
    for (int j = 0; j < colNumber; j++) { //列循环
      //处理每一个像素
      data[j] = data[j] / div * div + div / 2;
    }
  }
}

补充:简化指针运算,Mat类提供了ptr函数可以得到图像任意行的首地址。

uchar* data = outputImage.ptr<uchar>(i);//获取第i行的首地址
(2)用迭代器操作像素

说明:在迭代法中,获得图像矩阵的begin和end,然后增加迭代直至从begin到end。将*操作符添加在迭代指针前。

/*
  迭代器
*/
void colorReduce(Mat &inputImage, Mat& outputImage, int div)
{
  //参数准备
  outputImage = inputImage.clone();//复制实参到临时变量
  //获取迭代器
  Mat_<Vec3b>::iterator it = outputImage.begin<Vec3b>();//初始位置迭代器
  Mat_<Vec3b>::iterator itend = outputImage.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;//红
  }
}
(3)动态地址计算

说明:使用动态地址运算配合at方法的colorReduce函数的代码,这种方法简洁,便于对像素的直观认识。

/*
  动态地址法
*/
void colorReduce(Mat &inputImage, Mat& outputImage, int div)
{
  //参数准备
  outputImage = inputImage.clone();//复制实参到临时变量
  int rowNumber = outputImage.rows;//行数
  int colNumber = outputImage.cols;//行数

  //获取彩色图像像素
  for (int i = 0; i < rowNumber; i++) {
    for (int j = 0; j < colNumber; j++) {
      //开始处理每一个像素,0/1/2表示通道数
      outputImage.at<Vec3b>(i, j)[0] = outputImage.at<Vec3b>(i, j)[0] / div * div + div / 2;//蓝色通道
      outputImage.at<Vec3b>(i, j)[1] = outputImage.at<Vec3b>(i, j)[1] / div * div + div / 2;//绿色通道
      outputImage.at<Vec3b>(i, j)[2] = outputImage.at<Vec3b>(i, j)[2] / div * div + div / 2;//红色通道
    }
  }
}

补充:

  • Vec3b:由三个unsigned char组成的向量
  • image.at(i,j):取出灰度图像中i行j列的点。
  • image.at(i,j)[k]:取出彩色图像中i行j列第k通道的颜色点,k=[0,1,2],分别代表B,G,R。

实际效果:

相关文章
|
30天前
|
计算机视觉
Opencv学习笔记(三):图像二值化函数cv2.threshold函数详解
这篇文章详细介绍了OpenCV库中的图像二值化函数`cv2.threshold`,包括二值化的概念、常见的阈值类型、函数的参数说明以及通过代码实例展示了如何应用该函数进行图像二值化处理,并展示了运行结果。
286 0
Opencv学习笔记(三):图像二值化函数cv2.threshold函数详解
|
2月前
|
算法 计算机视觉
opencv图像形态学
图像形态学是一种基于数学形态学的图像处理技术,它主要用于分析和修改图像的形状和结构。
47 4
|
2月前
|
存储 计算机视觉
Opencv的基本操作(一)图像的读取显示存储及几何图形的绘制
本文介绍了使用OpenCV进行图像读取、显示和存储的基本操作,以及如何绘制直线、圆形、矩形和文本等几何图形的方法。
Opencv的基本操作(一)图像的读取显示存储及几何图形的绘制
|
3月前
|
算法 计算机视觉 Python
python利用opencv进行相机标定获取参数,并根据畸变参数修正图像附有全部代码(流畅无痛版)
该文章详细介绍了使用Python和OpenCV进行相机标定以获取畸变参数,并提供了修正图像畸变的全部代码,包括生成棋盘图、拍摄标定图像、标定过程和畸变矫正等步骤。
python利用opencv进行相机标定获取参数,并根据畸变参数修正图像附有全部代码(流畅无痛版)
WK
|
3月前
|
编解码 计算机视觉 Python
如何在OpenCV中进行图像转换
在OpenCV中,图像转换涉及颜色空间变换、大小调整及类型转换等操作。常用函数如`cvtColor`可实现BGR到RGB、灰度图或HSV的转换;`resize`则用于调整图像分辨率。此外,通过`astype`或`convertScaleAbs`可改变图像数据类型。对于复杂的几何变换,如仿射或透视变换,则可利用`warpAffine`和`warpPerspective`函数实现。这些技术为图像处理提供了强大的工具。
WK
105 1
|
5月前
|
算法 计算机视觉
【Qt&OpenCV 图像的感兴趣区域ROI】
【Qt&OpenCV 图像的感兴趣区域ROI】
154 1
|
4月前
|
机器学习/深度学习 XML 计算机视觉
OpenCV(Open Source Computer Vision Library)是一个开源的计算机视觉和机器学习库,它提供了大量的函数和工具,用于处理图像和视频数据。
OpenCV(Open Source Computer Vision Library)是一个开源的计算机视觉和机器学习库,它提供了大量的函数和工具,用于处理图像和视频数据。
|
5月前
|
运维 算法 计算机视觉
【Qt&OpenCV 图像的模板匹配 matchTemplate/minMaxLoc】
【Qt&OpenCV 图像的模板匹配 matchTemplate/minMaxLoc】
74 1
|
5月前
|
存储 编解码 算法
【Qt&OpenCV 检测图像中的线/圆/轮廓 HoughLinesP/HoughCircles/findContours&drawContours】
【Qt&OpenCV 检测图像中的线/圆/轮廓 HoughLinesP/HoughCircles/findContours&drawContours】
86 0
|
5月前
|
计算机视觉
OpenCV中图像算术操作与逻辑操作
OpenCV中图像算术操作与逻辑操作
65 1
下一篇
无影云桌面