zoukankan      html  css  js  c++  java
  • opencv-图像遍历

    #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;
    }

  • 相关阅读:
    归并排序(Merge Sort)
    AtCoder AGC035D Add and Remove (状压DP)
    AtCoder AGC034D Manhattan Max Matching (费用流)
    AtCoder AGC033F Adding Edges (图论)
    AtCoder AGC031F Walk on Graph (图论、数论)
    AtCoder AGC031E Snuke the Phantom Thief (费用流)
    AtCoder AGC029F Construction of a Tree (二分图匹配)
    AtCoder AGC029E Wandering TKHS
    AtCoder AGC039F Min Product Sum (容斥原理、组合计数、DP)
    AtCoder AGC035E Develop (DP、图论、计数)
  • 原文地址:https://www.cnblogs.com/mrcharles/p/11879790.html
Copyright © 2011-2022 走看看