/*
*本程序是学会使用: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 ;
}