学习OpenCV(二)

/*
*本程序是学会使用:1、用下标访问像素,2、使用迭代器访问像素 , 3、使用指针访问像素
*4、把图像写入磁盘
*
*
*/

#include "highgui.h"

//访问元素用下标
void salt(cv::Mat &img , int n)
{
	for(int k = 0 ; k < n ; ++ k)
	{
		int i = rand() % img.cols ;
		int j = rand() % img.rows ;
		if(1 == img.channels())
		{
			img.at<uchar>(j , i) = 255 ;
		}
		else if(3 == img.channels())
		{
			img.at<cv::Vec3b>(j , i)[0] = 255 ;
			img.at<cv::Vec3b>(j , i)[1] = 255 ;
			img.at<cv::Vec3b>(j , i)[2] = 255 ;
		}
	}
	//扩展:
	//cv::Mat_<uchar> im1 = img ;
	//im1(50 , 100) = 0 ;//对于已经知道返回类型时 可以这样访问元素
}

//减少图像颜色数
void colorReduce(cv::Mat &img , int div = 64)
{
	int rowsNum = img.rows ;
	int closPiexlNum = img.cols * img.channels() ;

	for(int i = 0 ; i < rowsNum ; ++ i)
	{
		uchar *data = img.ptr<uchar>(i) ;
		for(int j = 0 ; j < closPiexlNum ; ++ j)
		{
			data[j] = data[j] / div * div + div / 2 ;
		}
	}
}


void colorReduce3(cv::Mat img , cv::Mat &result , int div = 64)
{
	result.create(img.rows , img.cols , img.type()) ;

	int rowsNum = img.rows ;
	int closPiexlNum = img.cols * img.channels() ;

	for(int i = 0 ; i < rowsNum ; ++ i)
	{
		uchar *data_in = img.ptr<uchar>(i) ;
		uchar *data_out = result.ptr<uchar>(i) ;
		for(int j = 0 ; j < closPiexlNum ; ++ j)
		{
			data_out[j] = data_in[j] / div * div + div / 2 ;
		}
	}
}

void colorReduce4(cv::Mat img , cv::Mat &result , int div = 64)
{
	//result.create(img.rows , img.cols , img.type()) ;
	result = img.clone() ;
	//注意两种迭代器的定义方法
	cv::MatIterator_<cv::Vec3b>   itStart = result.begin<cv::Vec3b>() ;
	cv::Mat_<cv::Vec3b>::iterator itEnd = result.end<cv::Vec3b>() ;

	while(itStart != itEnd)
	{
		(*itStart)[0] = (*itStart)[0] / div * div + div / 2 ;
		(*itStart)[1] = (*itStart)[1] / div * div + div / 2 ;
		(*itStart)[2] = (*itStart)[2] / div * div + div / 2 ;
		itStart ++ ;
	}
	//Const迭代器两种定义方法
	//cv::MatConstIterator_<cv::Vec3b> it ;
	//cv::Mat_<cv::Vec3b>::const_iterator it ;
}

void colorReduce5(cv::Mat img , cv::Mat &result , int div = 64)
{
	result = img.clone() ;

	int rNum = result.rows ;
	int cNum = result.cols ;

	if(result.isContinuous())
	{
		cNum *= rNum ;
		rNum = 1 ;
	}

	int n = static_cast<int>(log(static_cast<double>(div)) / log(2.0)) ;
	uchar mask = 0xFF << n ;

	for(int i = 0 ; i < rNum ; ++ i)
	{
		uchar *data = result.ptr<uchar>(i) ;
		for(int j = 0 ; j < cNum ; ++ j)
		{
			*data++ = *data & mask + div / 2 ;
			*data++ = *data & mask + div / 2 ;
			*data++ = *data & mask + div / 2 ;
		}
	}
}

void colorReduce6(cv::Mat img , cv::Mat &result , int div = 64)
{
	int n = static_cast<int>(log(static_cast<double>(div)) / log(2.0)) ;
	uchar mask = 0xFF << n ;

	result = (img & cv::Scalar(mask , mask , mask) 
		      + cv::Scalar(div / 2 , div / 2 , div / 2)) ;
}

int main()
{
	cv::Mat img ;
	img = cv::imread("D:/Development/OpenCV/images/boldt.jpg") ; 

	cv::namedWindow("Original") ;
	cv::imshow("Original" , img) ;

	//salt(img , 3000) ;
	
	//colorReduce(img , 64) ;

	//cv::Mat imgClone = img.clone() ;

	cv::Mat result ;
	//colorReduce3(img , result) ;//使用指针
	//colorReduce4(img , result) ;//使用迭代器
	//colorReduce5(img , result) ;//使用位运算
	colorReduce6(img , result) ;//简洁的写法

	cv::namedWindow("Result") ;
	cv::imshow("Result" , result) ;

	//cv::imwrite("result.jpg" , img) ;//把图像写在磁盘上
	cv::waitKey() ;

	return 0 ;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值