颜色缩减 -利用指针、迭代器、动态地址实现访问像素

为什么要使用颜色缩减

在对单通道图像进行处理时,像素的可能值为256个,但处理多通道时,像素的处理就会相当麻烦,其实用这些颜色中具有代表性的一小部分就可以达到同样的效果,所以颜色空间缩减就可以派上用场了。一个信道(channel)有256个不同的值(2^8=256),但是如果使用的是GRB方案,三个channel的话,颜色的数量就会变为256256256,大概是16个million这么多,这么多的颜色数量,对于计算机来说仍然是一个负担,所以可以想一些方法来降低这些色彩数量。

颜色缩减简单原理

公式:I_new = (I_old/10)*10; //利用int类型向下取整的特点

代码:

/******************************颜色空间缩减*******************************************/
//颜色空间缩减:将现有的颜色空间值除以某个输入值,以获得较少的颜色数,比如:颜色值0-9->0,10-19->10,以此类推
//公式:I_new = (I_old/10)*10;	//利用int类型向下取整的特点
//可以将256种计算结果存入表table中
/*
int divdeWith = 10;
uchar table[256];
for(int i=0;i<256;++i)
{table[i]= divdeWith * (i/divdeWith);		//table[i]存放的是值为i的像素缩小颜色空间的结果
}
p[j]=table[p[j]];
算法步骤:
1、遍历图像矩阵的每一个像素
2、对像素应用上述公式
*/
/************************通过指针、迭代器、动态地址访问元素 进行颜色缩减****************************************/
/*
访问像素的三种方法:
1、指针访问:C操作符[];
2、迭代器 :iterator
3、动态地址计算
*///-----------------------------------------------颜色缩减函数------------------------------------------------
void colorReduce(Mat& inputImage,Mat& outputImage,int div,int type);//-----------------------------------------------主函数------------------------------------------------
int main()
{Mat srcImage = imread("D:\\opencv_picture_test\\miku2.jpg", 2 | 4);namedWindow("原始图", WINDOW_NORMAL);//WINDOW_NORMAL允许用户自由伸缩窗口imshow("原始图", srcImage);Mat dstImage;dstImage.create(srcImage.rows, srcImage.cols, srcImage.type());	//大小类型和原图一样double time0 = static_cast<double>(getTickCount());	//记录起始时间//颜色缩减colorReduce(srcImage, dstImage,128,3);//一系列处理之后time0 = ((double)getTickCount() - time0) / getTickFrequency();cout << "此方法运行时间为:" << time0 << "秒" << endl;	//输出运行时间namedWindow("效果图", WINDOW_NORMAL);//WINDOW_NORMAL允许用户自由伸缩窗口imshow("效果图", dstImage);imwrite("D:\\opencv_picture_test\\miku5.jpg", dstImage);waitKey(0);return 0;}
//-----------------------------------------------colorReduce()函数------------------------------------------------
void colorReduce(Mat& inputImage, Mat& outputImage, int div, int type)
{//描述:使用指针访问 ,很好理解,和C类似if (type == 1){outputImage = inputImage.clone();		//因为我们需要进行处理时不对原图像产生影响,所以这里使用深复制int row_num = outputImage.rows;			//行数int col_num = outputImage.cols * outputImage.channels();			//列数*通道数 = 每一行元素的个数   灰度图通道数为1,彩色的为3//双重循环,遍历所有像素值for (int i = 0;i < row_num;i++)	//行循环{uchar* data = outputImage.ptr<uchar>(i);		//获取第i行的首地址for (int j = 0;j < col_num;j++)	//列循环{data[j] = data[j] / div * div;	//颜色缩减,也可以是其他的一些处理}}}//描述:使用迭代器访问/*我们仅仅需要获得图像矩阵的begin和end,然后增加迭代直至begin到end。将*操作符添加在迭代指针前,即可访问当前指向的内容,相比用指针直接访问可能出现的越界问题,迭代器绝对是非常安全的*/else if (type == 2){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;(*it)[1] = (*it)[1] / div * div;(*it)[2] = (*it)[2] / div * div;//-------【处理结束】---------------}}//描述:使用动态地址运算配合at访问else{outputImage = inputImage.clone();		//因为我们需要进行处理时不对原图像产生影响,所以这里使用深复制int row_num = outputImage.rows;			//行数int col_num = outputImage.cols ;			//列数//双重循环,遍历所有像素值for (int i = 0;i < row_num;i++)	//行循环{	for (int j = 0;j < col_num;j++)	//列循环{//-------【开始处理每个像素】---------------outputImage.at<Vec3b>(i, j)[0] = outputImage.at<Vec3b>(i, j)[0] / div * div;		//B通道outputImage.at<Vec3b>(i, j)[1] = outputImage.at<Vec3b>(i, j)[1] / div * div;		//G通道outputImage.at<Vec3b>(i, j)[2] = outputImage.at<Vec3b>(i, j)[2] / div * div;		//R通道//-------【处理结束】---------------}}/*讲解:成员函数at(int y,int x)可以用来存取图像元素,但在编译时需要知道图像的数据类型,at方法本身不会对任何数据类型进行转化,十分重要!!!存取彩色图像的代码可以写成如下形式:image.at<Vec3b>(j,i)[channel] =value;opencv彩色图像的顺序存储是按照BGR不是RGB!!!!*/		}
}
/****************************************************************/

处理效果:

原图
效果图

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

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

相关文章

PowerShell_9_零基础自学课程_9_高级主题:静态类和类的操作

哈哈&#xff0c;昨天弄了个ubuntu 11.10在虚拟机上运行&#xff0c;发现11.10界面非常绚丽&#xff0c;但是其需要的系统资源非常多&#xff0c;我虚拟机设定内存为512M&#xff0c;1个CPU4个核心&#xff0c; 进入以后发现根本动不了&#xff0c;因此今天我就下载了一个Fedor…

05-图像的平滑处理(不同的滤波操作)

对图像进行平滑处理实则就是对图像进行滤波操作罢了 每张图片都有若干个像素点所构成&#xff0c;滤波操作上就是将照片上的某些部分像素点进行修改从而达到平滑的效果 先展示一下原图 import cv2 img cv2.imread(E:\Jupyter_workspace\study\data/test1.png)cv2.imshow(te…

C++设计模式之Abstract Factory模式

一、功能   提供一个创建一系列相关或相互依赖对象的接口&#xff0c;而无需指定它们具体的类。 二、结构图类厂最基本的结构示意图如下&#xff1a; 在实际应用中&#xff0c;类厂模式可以扩充到很复杂的情况&#xff0c;如下图所示&#xff1a; 三、优缺点 优点&#xff1…

数字图像处理小练习存档1

小练习的题目&#xff1a; 1、读取一张图&#xff0c;分解RGB三个通道 /************练习1**********************/ int main() {Mat img1 imread("D:\\opencv_picture_test\\miku2.jpg",2|4); //灰度图if (img1.empty()){printf("Could not find the imag…

06-对图像进行腐蚀操作

形态学中的腐蚀操作一般处理的图像数据为二值的 cv2.erode(img,kernel,iterations 1) kernel表示拿多大的卷积核去腐蚀 iterations表示迭代次数 可以将一些带有毛毛的图像去毛毛化 原图 import cv2 import numpy as npdef show_photo(name,picture):cv2.imshow(name,picture)…

Opencv实现利用滑动条来调整阈值

#include <opencv2/opencv.hpp> #include <iostream>using namespace cv; using namespace std; #define WINDOW_NAME "【程序窗口】" //为窗口标题定义的宏 //*--------------------------【练习】利用滑动条来调整阈值-----------------------------…

07-对图像进行膨胀操作

形态学中的膨胀操作即让照片变得更大&#xff0c;与腐蚀操作互为逆运算 cv2.dilate(erosion,kernel,iterations 1) 第一个参数&#xff1a;图像对象名称 第二个参数&#xff1a;卷积核的大小 第三个参数&#xff1a;迭代次数 此时就可与腐蚀操作进行相结合&#xff0c;腐蚀去毛…

08-开运算和闭运算

开运算和闭运算实则就是将腐蚀操作和膨胀操作结合而已&#xff0c;也就是个先后循序罢了 开运算&#xff1a;先腐蚀再膨胀 闭运算&#xff1a;先膨胀再腐蚀 cv2.morphologyEx(img_open,cv2.MORPH_OPEN,kernel) cv2.morphologyEx(img_close,cv2.MORPH_CLOSE,kernel) 第一个参数…

连通域标记——实现硬币自动计件

前言 在自动计算图像中有几枚硬币的任务中&#xff0c;分离出前景和背景后是否就可以马上实现自动计件&#xff0c;如果可以&#xff0c;如何实现&#xff1f;如果不可以&#xff0c;为什么&#xff1f; 答案是否定的。二值化之后我们的得到的只是前景总像素的多少&#xff0c…

09-梯度运算

梯度运算膨胀操作-腐蚀操作&#xff0c;这里的-操作是图像的减法&#xff0c;可不是简单的加减乘除运算 为了更加形象生动&#xff0c;先将膨胀和腐蚀操作的结果进行合并展示&#xff0c;然后再与梯度运算进行比较 cv2.morphologyEx(pie,cv2.MORPH_GRADIENT,kernel) 第一个参数…

Unity-Shader-渲染队列

Unity-Shader-渲染队列 渲染简介Unity中的几种渲染队列Background (1000)最早被渲染的物体的队列。Geometry (2000) 不透明物体的渲染队列。大多数物体都应该使用该队列进行渲染&#xff0c;也就是Unity Shader中默认的渲染队列。AlphaTest (2450) 有透明通道&#xff0c;需要进…

形态学操作——腐蚀与膨胀

预备知识 结构元&#xff08;SE&#xff09; 1、结构元的中心一般来说是放在其重心位置处&#xff0c;但原则上原点的选择是依赖于你要解决的问题的。 2、对图像操作时&#xff0c;我们要求结构元是矩形阵列。&#xff08;在结构元的基础上添加较少的背景元素实现&#xff09…

10-礼帽与黑帽操作

cv2.morphologyEx(img,cv2.MORPH_TOPHAT,kernel) 第一个参数&#xff1a;图像对象名称 第二个参数&#xff1a;运算类型TOPHAT为礼帽运算 第三个参数&#xff1a;卷积核的大小 礼帽运算&#xff1a;原始的输入-开运算&#xff08;先腐蚀再膨胀&#xff09; 原始带刺儿&#xff…

形态学操作——开闭运算、顶帽底(黑)帽变换

膨胀和腐蚀运算的问题&#xff1a; 边缘形状发生了变化&#xff0c;膨胀发生了扩张&#xff0c;腐蚀发生了收缩 目标物体变形&#xff0c;对识别时的特征提取会造成影响 解决方法&#xff1a; 开操作: B对A的开操作就是先B对A腐蚀&#xff0c;紧接着用B对结果进行膨胀 先腐…

11-图像梯度-Sobel算子

图像梯度是指图像某像素在x和y两个方向上的变化率&#xff08;与相邻像素比较&#xff09;&#xff0c;是一个二维向量&#xff0c;由2个分量组成&#xff0c;X轴的变化、Y轴的变化 。 其中X轴的变化是指当前像素右侧&#xff08;X加1&#xff09;的像素值减去当前像素左侧&…

形态学操作——击中击不中变换

操作目的 HitMiss变换是形态检测的一个工具&#xff0c;通过定义形状模板可以在图像中获取同一形状物体的位置坐标。 算法讲解 1、用击中结构去腐蚀原始图像得到击中结果X&#xff08;这个过程可以理解为在原始图像中寻找和击中结构完全匹配的模块&#xff0c;匹配上了之后&…

12-图像梯度-Scharr算子和laplacian算子

Scharr算子 cv2.Scharr(img,cv2.CV_64F,1,0) 第一个参数&#xff1a;当前的图像对象名称 第二个参数&#xff1a;当前图像的深度&#xff0c;通常情况下指定为-1&#xff0c;表示输出和输入的深度是一样的&#xff1b;cv2.CV_64F可以存6字节的大小&#xff0c;为了方便后面的取…

Opencv——图像金字塔与图像尺寸缩放

主要讲解 1、resize()函数调用 函数定义&#xff1a; 调用方式&#xff1a; resize(srcImage, dstImage, Size(64, 128)); //对图片进行修改 resize(srcImage, dstImage, Size(), 0.5, 0.5);第6个参数的含义&#xff1a; INTER_NEAREST:最邻近插值 (放大好用) INTER_ARE…

13-Canny边缘检测

Canny边缘检测主要思路步骤如下&#xff1a; 1&#xff0c;使用高斯滤波器&#xff0c;以平滑图像&#xff0c;滤除噪声 2&#xff0c;计算图像中每个像素点的梯度强度和方向 3&#xff0c;应用非极大值抑制&#xff0c;以消除边缘检测带来的杂散响应 4&#xff0c;应用双阈值检…

微机原理——移位指令

例题 思路 选择移位语句&#xff0c;右移&#xff0c;将AL移出的送入DX左端&#xff0c;将BL移出的送入DX左端。循环八次 MOV AL,01100101B; MOV BL,11011010B; XOR DX,DX;两个值相同&#xff0c;异或结果为0。等效&#xff1a;MOV DX,0 MOV CX,8;count L1: SHR AL,1;逻辑右…