#include "stdafx.h"
#include<opencv2/opencv.hpp>
#include<iostream>
#include<cmath>
#include "tools.h" using namespace cv;
using namespace std; /*
还是使用经典的Reduce Color的例子,即对图像中的像素表达进行量化。如常见的RGB24图像有256×256×256颜色,
通过Reduce Color将每个通道的像素减少8倍至256 / 8 = 32种,则图像只有32×32×32种颜色。
假设量化减少的倍数是N,则代码实现时就是简单的value / N*N,通常我们会再加上N / 2以得到相邻的N的倍数的中间值,
最后图像被量化为(256 / N)×(256 / N)×(256 / N)种颜色。
并对图像降色彩后的彩色直方图进行统计。
*/
/*方法一、直接对图像像素修改.at<typename>(i, j)
Mat类提供了一个at的方法用于取得图像上的点,它是一个模板函数,可以取到任何类型的图像上的点。*/
void colorReduceWithAt(Mat& image, int div)
{
for (int i = 0; i<image.rows; i++)
{
for (int j = 0; j<image.cols; j++)
{
image.at<Vec3b>(i, j)[0] = image.at<Vec3b>(i, j)[0] / div*div + div / 2;//其中uchar,Vec3b都是图像像素值的类型,不要对Vec3b这种类型感觉害怕,其实在core里它是通过typedef Vec<T,N>来定义的,N代表元素的个数,T代表类型。
image.at<Vec3b>(i, j)[1] = image.at<Vec3b>(i, j)[1] / div*div + div / 2;
image.at<Vec3b>(i, j)[2] = image.at<Vec3b>(i, j)[2] / div*div + div / 2;
//Mat_<uchar> im=image;im(i, j) = im(i, j) / div*div + div / 2;
}
}
}
//二、用指针.ptr<uchar>(k)来遍历输入图像,数组[]生成输出图像
//上面的例程中可以看到,我们实际喜欢把原图传进函数内,但是在函数内我们对原图像进行了修改,而将原图作为一个结果输出,很多时候我们需要保留原图,这样我们需要一个原图的副本。
void colorReduce(const Mat& image, Mat& outImage, int div)
{
// 创建与原图像等尺寸的图像
outImage.create(image.size(), image.type());
int nr = image.rows;
// 将3通道转换为1通道
int nl = image.cols*image.channels();
for (int k = 0; k<nr; k++)
{
// 每一行图像的指针
const uchar* inData = image.ptr<uchar>(k);
uchar* outData = outImage.ptr<uchar>(k);
for (int i = 0; i<nl; i++)
{
outData[i] = inData[i] / div*div + div / 2;
}
}
}
//三、用指针.ptr<uchar>(k)来遍历输入图像,指针方式生成输出图像
void colorReduceptr(const Mat& image, Mat& outImage, int div)
{
// 创建与原图像等尺寸的图像
outImage.create(image.size(), image.type());
int nr = image.rows;
// 将3通道转换为1通道
int nl = image.cols*image.channels();
for (int k = 0; k<nr; k++)
{
// 每一行图像的指针
const uchar* inData = image.ptr<uchar>(k);
uchar* outData = outImage.ptr<uchar>(k);
for (int i = 0; i<nl; i++)
{
*outData++ = *inData++ / div*div + div / 2;
}
}
}
//四、用指针.ptr<uchar>(k)来遍历输入图像,指针方式结合位运算生成输出图像
void colorReduceptrBit(const Mat& image, Mat& outImage, int div)
{
// 创建与原图像等尺寸的图像
outImage.create(image.size(), image.type());
int nr = image.rows;
// 将3通道转换为1通道
int nl = image.cols*image.channels();
//对数换底公式log a(b) = log b/log a
int n = static_cast<int>(log(static_cast<double>(div)) / log(2.0));
// mask used to round the pixel value e.g. for div=16, mask= 0xF0
uchar mask = 0xFF << n;
for (int k = 0; k<nr; k++)
{
// 每一行图像的指针
const uchar* inData = image.ptr<uchar>(k);
uchar* outData = outImage.ptr<uchar>(k);
for (int i = 0; i<nl; i++)
{
//进行位运算时要注意加括号,位运算优先级低于+-*/
*outData++ = (*inData++ & mask) + div / 2;
}
}
}
//七、迭代器Mat_iterator方法。
/*
下面的方法可以让我们来为图像中的像素声明一个迭代器:
MatIterator_<Vec3b> it;
Mat_<Vec3b>::iterator it;
如果迭代器指向一个const图像,则可以用下面的声明:
MatConstIterator<Vec3b> it; 或者
Mat_<Vec3b>::const_iterator it;
*/
void colorReduceIterator(const Mat& image, Mat& outImage, int div)
{
outImage.create(image.size(), image.type());
MatConstIterator_<Vec3b> it_in = image.begin<Vec3b>();
MatConstIterator_<Vec3b> itend_in = image.end<Vec3b>();
MatIterator_<Vec3b> it_out = outImage.begin<Vec3b>();
MatIterator_<Vec3b> itend_out = outImage.end<Vec3b>();
while (it_in != itend_in)
{
(*it_out)[0] = (*it_in)[0] / div*div + div / 2;
(*it_out)[1] = (*it_in)[1] / div*div + div / 2;
(*it_out)[2] = (*it_in)[2] / div*div + div / 2;
it_in++;
it_out++;
}
} int main2(int argc, const char** argv)
{
Mat image;
image = imread("Lenna.png", IMREAD_COLOR);
namedWindow("before");
imshow("before", image);
namedWindow("after");
colorReduceWithAt(image, 8);
imshow("after", image);
Mat srcHistImage = Mat::zeros(256, 256, CV_8UC1); drawHistImg(image, srcHistImage, "srcHistImage"); cvWaitKey(-1);
destroyAllWindows();
return 0;
}

opencv-图像遍历的更多相关文章

  1. opencv——图像遍历以及像素操作

    摘要 我们在图像处理时经常会用到遍历图像像素点的方式,在OpenCV中一般有四种图像遍历的方式,在这里我们通过像素变换的点操作来实现对图像亮度和对比度的调整. 补充: 图像变换可以看成 像素变换--点 ...

  2. opencv——图像直方图与反向投影

    引言 在图像处理中,对于直方图这个概念,肯定不会陌生.但是其原理真的可以信手拈来吗? 本文篇幅有点长,在此列个目录,大家可以跳着看: 分析图像直方图的概念,以及opencv函数calcHist()对于 ...

  3. OpenCV图像金字塔:高斯金字塔、拉普拉斯金字塔与图片尺寸缩放

    这篇已经写得很好,真心给作者点个赞.题目都是直接转过来的,直接去看吧. Reference Link : http://blog.csdn.net/poem_qianmo/article/detail ...

  4. 【OpenCV新手教程之十三】OpenCV图像金字塔:高斯金字塔、拉普拉斯金字塔与图片尺寸缩放

    本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接:http://blog.csdn.net/poem_qianmo/article/details/26157633 作者:毛星云(浅墨) ...

  5. Opencv 图像叠加 添加水印

    Opencv 图像叠加 添加水印 C++: void Mat::copyTo(OutputArray m) const C++: void Mat::copyTo(OutputArray m, Inp ...

  6. opencv图像读取-imread

    前言 图像的读取和保存一定要注意imread函数的各个参数及其意义,尽量不要使用默认参数,否则就像数据格式出现错误(here)一样,很难查找错误原因的: re: 1.opencv图像的读取与保存; 完

  7. 学习 opencv---(12)OpenCV 图像金字塔:高斯金字塔,拉普拉斯金字塔与图片尺寸缩放

    在这篇文章里,我们一起学习下 图像金字塔 的一些基本概念,如何使用OpenCV函数pyrUp和pyrDown 对图像进行向上和向下采样,以及了解专门用于缩放图像尺寸的resize函数的用法.此博文一共 ...

  8. [OpenCV Qt教程] 在Qt图形界面中显示OpenCV图像的OpenGL Widget(第二部分)

    本文译自:http://www.robot-home.it/blog/en/software/tutorial-opencv-qt-opengl-widget-per-visualizzare-imm ...

  9. [OpenCV Qt教程] 在Qt图形界面中显示OpenCV图像的OpenGL Widget (第一部分)

    本文译自:http://www.robot-home.it/blog/en/software/tutorial-opencv-qt-opengl-widget-per-visualizzare-imm ...

  10. 关于OpenCV图像操作的默认参数问题

    本系列文章由 @yhl_leo 出品,转载请注明出处. 文章链接: http://blog.csdn.net/yhl_leo/article/details/51559490 在使用OpenCV以及其 ...

随机推荐

  1. [转] undefined reference to `clock_gettime'

    下面这个错误通常是因为链接选项里漏了-lrt,但有时发现即使加了-lrt仍出现这个问题,使用nm命令一直,会发现-lrt最终指向的文件 没有包含任何symbol,这个时候,可以找相应的静态库版本lib ...

  2. 关于Mysql分区和分表

    [分区概念]分区就是把一张表的数据按照一定的规则分成多个区块,这些区块可以在同一个磁盘上,也可以在不同的磁盘上.分区后表还是一张表.分区根据一定的规则把数据文件和索引文件进行了分割,还多出了一个.pa ...

  3. 2019 牛客多校第三场 B Crazy Binary String

    题目链接:https://ac.nowcoder.com/acm/contest/883/B 题目大意   给定一个长度为 N 的 01 字符串,输出最长子串和子序列的长度,满足其中 0 和 1 的个 ...

  4. Python环境出现模块找不到

    由于上周脚受伤了,修养了几天没有学习.今天去实验室发现我的编译器跑不动了,出现找不到模块的情况,很奇怪都安装了,也不会提示什么模块找不到. 查找了些资料,发现是因为某个模块的文件损坏或者被覆盖或者安装 ...

  5. SSM 整合 Shiro

    1. 导包 <!-- spring --> <dependency> <groupId>org.springframework</groupId> &l ...

  6. java-day15

    File类 文件和目录路径名的抽象表示,主要用于文件和目录的创建.查找和删除等操作 静态成员 static String pathSeparator 路径分隔符 File.pathSeparator ...

  7. python 数据结构之冒泡排序

    def bubble_sort(alist): # 外层循环冒泡排序进行的次数(len-1) for i in range(len(alist) - 1, 0, -1): # 内层循环控制冒泡的比较: ...

  8. centos6.5离线安装pandas

    由于笔记本跑不动很多大赛的数据,遂转至申请的虚拟机(centos6.5)中,奈何学校的虚拟机没网,就开始了离线安装pandas的道路,当中有踩了好些坑,于是便产生了这篇文章~ 首先,自带的python ...

  9. 【模板篇】A* 寻路算法

    上次在做k短路的时候说到了A*, 但是并没有仔细的研究A*寻路, 毕竟k短路中的A*也不怎么标准… A*寻路的过程网上还是有很多的, 讲得也很清楚, 不妨跟着里面的图示自己动手操作一下, 基本一遍就能 ...

  10. MAMP 安装 php 扩展

    1.官网下载所对应的php 版本http://php.net/get/php-5.3.29.tar.gz/from/a/mirror 2.解压 找到需要的扩展目录 例如我要的是shmopcd ~/Do ...