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

  • 相关阅读:
    东芝线阵CCD芯片TCD1305DG驱动时序设计
    数字电路中应避免产生不必要的锁存器 Latch
    准双向口、开漏输出、推挽输出结构介绍
    边沿检测电路小结
    数字系统中的亚稳态及其解决办法
    launch edge 和 latch edge 延迟
    基于Verilog的偶数、奇数、半整数分频以及任意分频器设计
    找到了救命的东西 NVIDIA MPS (multi-process service)
    关于多个程序同时launch kernels on the same GPU
    java的System.currentTimeMillis()和System.nanoTime()
  • 原文地址:https://www.cnblogs.com/mrcharles/p/11879790.html
Copyright © 2020-2023  润新知