在了解了图像的基础知识和OpenCV的基础知识和操作以后,接下来我们要做的就对像素进行操作,我们知道了图像的本质就是一个矩阵,那么一个矩阵中存储了那么多的像素,我们如何来操作呢?下面通过几个例子来看看像素的操作。

这个是原图,接下来的例子都是对这个图片进行操作的。

访问像素出现雪花效果

我们需要有雪花的效果,这里的雪花其实就是一个个白色的点,白色在像素值是255,所以我们的思路就是在一个图像上面的矩阵中的一些像素值转成值为255的,如果是彩色的图像的话就是三个通道,那么就是分别对三个通道的值都转为255,三通道在OpenCV里面是按照蓝绿红的顺序排布的。

  • 代码实现


#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <random> // Add white noise to an image
void white(cv::Mat image, int n) { // C++11 random number generator
std::default_random_engine generator;
std::uniform_int_distribution<int> randomRow(0, image.rows - 1);
std::uniform_int_distribution<int> randomCol(0, image.cols - 1); int i,j;
for (int k=0; k<n; k++) {
// 生成图形位置
i= randomCol(generator);
j= randomRow(generator);
if (image.type() == CV_8UC1) { //灰度图像
// 单通道8位
image.at<uchar>(j,i)= 255;
} else if (image.type() == CV_8UC3) { // color image
// 3通道,分别是蓝绿红
image.at<cv::Vec3b>(j,i)[0]= 255;
image.at<cv::Vec3b>(j,i)[1]= 255;
image.at<cv::Vec3b>(j,i)[2]= 255;
// or simply:
// image.at<cv::Vec3b>(j, i) = cv::Vec3b(255, 255, 255);
}
}
} int main()
{
// open the image
cv::Mat image= cv::imread("boldt.jpg",1); // call function to add noise
white(image,3000); // display result
cv::namedWindow("Image1");
cv::imshow("Image1",image); // write on disk
cv::imwrite("salted.bmp",image); cv::waitKey(); // test second version
cv::Mat image2= cv::imread("boldt.jpg",0);//0表示灰度图 white(image2, 500); cv::namedWindow("Image2");
cv::imshow("Image2",image2); cv::waitKey(); return 0;
}
  • 效果

指针遍历像素:减少图像中颜色的数量

彩色图像由三通道像素组成,每个通道表示红、绿、蓝三原色中一种颜色的亮度值,每个数值都是8位无符号字符类型,因此颜色总数为 256×256×256,即超过 1600 万种颜色。

所以有时候为了降低分析的复杂性,需要减少图像中颜色的数量。

一种实现方法是把RGB空间细分到大小相等的方块中。例如,如果把每种颜色数量减少到 1/8,那么颜色总数就变为 32×32×32。将旧图像中的每个颜色值划分到一个方块,该方块的中间值就是新的颜色值;新图像使用新的颜色值,颜色数就减少了。

所以在这里的减少图像中颜色的数量的思路的步骤是:

  • 假设 N 是减色因子,将图像中每个像素的值除以 N(这里假 定使用整数除法,不保留余数)。

  • 然后将结果乘以 N,得到 N 的倍数,并且刚好不超过原始像素 值。

  • 加上 N / 2,就得到相邻的 N 倍数之间的中间值。

  • 对所有 8 位通道值重复这个过程,就会得到 (256 / N) × (256 / N) × (256 / N)种可能的颜色值。



#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp> void reduceColor(cv::Mat image, int div = 64)
{
int nl = image.rows;//行数
int nc = image.cols * image.channels();//每一行的像素数量 for (int i = 0; i < nl; ++i) {
//获取行i的地址
auto data = image.ptr<uchar>(i);
for (int j = 0; j < nc; ++j) {
//处理每一个像素
data[j] = data[j]/div*div + div/2;
}
}
} int main()
{
cv::Mat image = cv::imread("boldt.jpg"); reduceColor(image, 64);
cv::namedWindow("image");
cv::imshow("image", image);
cv::waitKey();
return 0;
}
  • 效果图

当然刚刚的这个代码是用普通的遍历完成的,我们也可以用迭代器完成对像素的遍历

void reduceColorNew(cv::Mat image, int div=64) {

    // div must be a power of 2
int n= static_cast<int>(log(static_cast<double>(div))/log(2.0) + 0.5);
// mask used to round the pixel value
uchar mask= 0xFF<<n; // e.g. for div=16, mask= 0xF0
uchar div2 = div >> 1; // div2 = div/2 // get iterators
cv::Mat_<cv::Vec3b>::iterator it= image.begin<cv::Vec3b>();
cv::Mat_<cv::Vec3b>::iterator itend= image.end<cv::Vec3b>(); // scan all pixels
for ( ; it!= itend; ++it) { // process each pixel --------------------- (*it)[0]&= mask;
(*it)[0]+= div2;
(*it)[1]&= mask;
(*it)[1]+= div2;
(*it)[2]&= mask;
(*it)[2]+= div2; // end of pixel processing ----------------
}
}

扫描图像并访问相邻像素

在图像处理中经常有这样的处理函数,它在计算每个像素的数值时,需要使用周边像素的值。 如果相邻像素在上一行或下一行,就需要同时扫描图像的多行。

我们将使用一个锐化图像的处理函数。它基于拉普拉斯算子。在图像处理领域有一个众所周知的结论:如果从图像中减去拉普拉斯算子部分,图像 的边缘就会放大,因而图像会变得更加尖锐。

实现思路:

  • 图像扫描中使用了三个指针
  • 一个表 示当前行、一个表示上面的行、一个表示下面的行
  • 另外,因为在计算每一个像素时都需要访问 与它相邻的像素,所以有些像素的值是无法计算的,比如第一行、最后一行和第一列、最后一列 的像素。
#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp> void sharpen(const cv::Mat &image, cv::Mat &result) { result.create(image.size(), image.type()); // allocate if necessary
int nchannels= image.channels(); for (int j= 1; j<image.rows-1; j++) { // for all rows (except first and last) const uchar* previous= image.ptr<const uchar>(j-1); // previous row
const uchar* current= image.ptr<const uchar>(j); // current row
const uchar* next= image.ptr<const uchar>(j+1); // next row uchar* output= result.ptr<uchar>(j); // output row for (int i=nchannels; i<(image.cols-1)*nchannels; i++) { // apply sharpening operator
*output++= cv::saturate_cast<uchar>(5*current[i]-current[i-nchannels]-current[i+nchannels]-previous[i]-next[i]);
}
} // Set the unprocess pixels to 0
result.row(0).setTo(cv::Scalar(0));
result.row(result.rows-1).setTo(cv::Scalar(0));
result.col(0).setTo(cv::Scalar(0));
result.col(result.cols-1).setTo(cv::Scalar(0));
} int main()
{
cv::Mat image= cv::imread("boldt.jpg");
if (!image.data)
return 0; cv::Mat result; double time= static_cast<double>(cv::getTickCount());
sharpen(image, result);
time= (static_cast<double>(cv::getTickCount())-time)/cv::getTickFrequency();
std::cout << "time= " << time << std::endl; cv::namedWindow("Image");
cv::imshow("Image",result); cv::waitKey(); return 0;
}

时间:time= 0.00339625

OpenCV操作像素的更多相关文章

  1. 学习Opencv 2.4.9(二) ---操作像素

    作者:咕唧咕唧liukun321 来自:http://blog.csdn.net/liukun321 本质上说一张图像就是由数值组成的矩阵.Opencv 2.x由 cv::Mat 这个数据结构来表示一 ...

  2. OpenCV坐标系与操作像素的四种方法

    像素是图像的基本组成单位,熟悉了如何操作像素,就能更好的理解对图像的各种处理变换的实现方式了. 1.at方法 第一种操作像素的方法是使用"at",如一幅3通道的彩色图像image的 ...

  3. Python图像处理丨基于OpenCV和像素处理的图像灰度化处理

    摘要:本篇文章讲解图像灰度化处理的知识,结合OpenCV调用cv2.cvtColor()函数实现图像灰度操作,使用像素处理方法对图像进行灰度化处理. 本文分享自华为云社区<[Python图像处理 ...

  4. 使用Canvas操作像素

    现代浏览器支持通过<video>元素播放视频.大多数浏览器也可以通过MediaDevices.getUserMedia() API访问摄像头.但即使这两件事结合起来,我们也无法直接访问和操 ...

  5. OpenCv图像像素操作

    1:像素 有两种直接操作像素点的方法: 第一种: 将其转化为numpy.array格式,直接进行操作. 第二种:使用Opencv提供的Get1D,Get2D等函数. 2:获取行和列像素 有一下四个函数 ...

  6. 【OpenCV】像素操作的数字图像处理

    之前几天捣鼓matlab,用来处理数字图像,矩阵操作什么的,如果忘记线性代数就真的GG了. 在用了matlab被深深地吐槽之后,决定改用opencv,C++貌似也是处理数字图像的很好的工具 1. 在u ...

  7. python opencv:像素操作

    图片的像素 像素:组成图片的单位 RGB:颜色由 RGB三种颜色组成 颜色深度:对于8bit的颜色深度来说,它可以表示的颜色范围是 0 ~ 255,对于RGB图片来说,8位颜色深度可以表示 (2^8) ...

  8. 【从零学习openCV】opecv操作像素

    1. 存取像素值 在opencv中能够直接对cv::Mat类型的图像调用at函数读取或赋值某个像素,我们用个简单的案例来说明: //在一张图像上增加椒盐噪声,image为输入图像.n为噪点个数 voi ...

  9. OpenCV 学习之路(2) -- 操作像素

    本节内容: 访问像素值 用指针扫描图像 用迭代器扫描图像 编写高效的图像扫描循环 扫描图像并访问相邻像素 实现简单的图像运算 图像重映射 访问像素值 准备工作: 创建一个简单函数,用它在图像中加入椒盐 ...

随机推荐

  1. NGUI和UGUI图片字 艺术字(Bitmap图片转文字)制作方法

    用图片字而不是图片 美术和程序的配合,需要程序能够很快抓住问题重点并提出解决方案.美术出的图片字比我们使用的字体更好好看,那么是否要一个个图片去拼成数字呢? NGUI创建图片字 准备材料 美术提供的数 ...

  2. mySQL 约束 (Constraints)

    约束用于限制加入表的数据的类型: 1.创建表时规定约束(通过 CREATE TABLE 语句) 2.表创建之后也可以(通过 ALTER TABLE 语句). 约束类型: NOT NULL(非空) UN ...

  3. Python实例---模拟微信网页登录(day2)

    第三步: 实现长轮询访问服务器---day2代码 settings.py """ Django settings for weixin project. Generate ...

  4. Git Flow 工作模型与使用

    一. Git Flow 工作模型的原理 无规矩不成方圆,但是规矩太多了,则感觉到束缚.我们一个人工作的时候喜欢无拘无束,想怎么干就怎么干,没有人评判,没有人检验.时间久了就会盲目自大,以为增删改查熟悉 ...

  5. 【2017下集美大学软工1412班_助教博客】个人作业2——APP案例分析

    作业要求 个人作业2:APP案例分析 评分结果 按从高到低排列 学号后三位 第二次作业 Total 008 APP案例分析 23 044 第2次作业 19.5 011 App案例分析--XBMC 19 ...

  6. [提权]域内提权神器 MS14-068 完整EXP

     可以让任何域内用户提升为域管理员     c:\python27\python.exe ms14-068.py -u k8test3@k8.local -p k8team!@# -s S-1-5-2 ...

  7. Spring-IOC XML 配置多个相同 ID 的 bean 加载分析

    我们现在仍以 xml 中配置 bean 的方式来 使用 Spring ,不考虑注解和扫包 配置相同id 的bean 定义一个 bean 类 TransactionManager /** * @auth ...

  8. Git branch -r 无法获取远程分支,ui可以看见分支但是git 命令无法查看解决方案

    zhc@hongchangfirst$ git checkout -b hongchangfirst origin/hongchangfirst 出现: fatal: Cannot update pa ...

  9. 有意思的flex 色子布局

    <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...

  10. Qt入门之基础篇 ( 一 ) :Qt4及Qt5的下载与安装

    转载请注明出处:CN_Simo. 导语: Qt是一个跨平台的C++图形界面应用程序框架.它提供给开发者建立图形用户界面所需的功能,广泛用于开发GUI程序,也可用于开发非GUI程序.Qt很容易扩展,并且 ...