- 本文为@源码人原创文章,转载请注明出处
- 文章链接:https://blog.csdn.net/q_z_r_s
- 准备工作
为了说明图像扫描的过程, 我们来做一个简单的任务: 减少图像中颜色的数量。彩色图像由三通道像素组成, 每个通道表示红、 绿、 蓝三原色中一种颜色的亮度值, 每个数值都是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)种可能的颜色值。(摘录自:OpenCV计算机视觉编程攻略) - 算法实现
//colorReduce.hpp #include <iostream> #include <opencv2/core/core.hpp> #include <opencv2/imgproc/imgproc.hpp> using namespace std; using namespace cv; class colorReduce { public: int div; colorReduce():div(64){}; colorReduce(int div):div(div){}; ~colorReduce(){}; void colorReduce0(Mat& src, Mat& des); void colorReduce1(Mat& src, Mat& des); void colorReduce2(Mat& src, Mat& des); private: bool check(Mat& src, Mat& des); };
头文件中主要使用了三种不同的方法来访问像素,减色原理都是相同的,下面是算法实现:
//colorReduce.cpp #include "colorReduce.hpp" #include <iostream> #include <opencv2/core/core.hpp> #include <opencv2/imgproc/imgproc.hpp> using namespace std; using namespace cv; bool colorReduce::check(Mat& src, Mat& des) { if (src.empty()) { cout << "invalid image" << endl; return 1; } des.create(Size(src.cols, src.rows), src.type()); if (des.rows < src.rows || des.cols < src.cols || des.type() != src.type()) { cout << "target imgae is too small!" << endl; return 1; } return 0; } void colorReduce::colorReduce0(Mat& src, Mat& des) { if(!check(src, des)) { int rows = src.rows; int cols = src.cols; for (int i=0; i<rows; i++) { for (int j=0; j<cols; j++) { des.at<Vec3b>(i,j)[0] = src.at<Vec3b>(i,j)[0]/div*div + div/2; des.at<Vec3b>(i,j)[1] = src.at<Vec3b>(i,j)[1]/div*div + div/2; des.at<Vec3b>(i,j)[2] = src.at<Vec3b>(i,j)[2]/div*div + div/2; } } } } void colorReduce::colorReduce1(Mat& src, Mat& des) { if(!check(src, des)) { int rows = src.rows; int nc = src.step; for (int i=0; i<rows; i++) { uchar * srcptr = src.ptr<uchar>(i); uchar * desptr = des.ptr<uchar>(i); for (int j=0; j<nc; j++) { desptr[j] = srcptr[j]/div*div + div/2; } } } } void colorReduce::colorReduce2(Mat& src, Mat& des) { if(!check(src, des)) { MatIterator_<Vec3b> it_src_begin = src.begin<Vec3b>(); MatIterator_<Vec3b> it_src_end = src.end<Vec3b>(); //等价于Mat_<Vec3b>::iterator it = src.begin(); //typedef MatIterator_<_Tp> iterator; MatIterator_<Vec3b> it_des_begin = des.begin<Vec3b>(); //MatIterator_<Vec3b> it_des_end = des.end<Vec3b>(); for (; it_src_begin != it_src_end; it_src_begin++, it_des_begin++) { (*it_des_begin)[0] = (*it_src_begin)[0]/div*div + div/2; (*it_des_begin)[1] = (*it_src_begin)[1]/div*div + div/2; (*it_des_begin)[2] = (*it_src_begin)[2]/div*div + div/2; } } }
效果展示: