1.指针访问像素,缩小颜色空间
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
using namespace std;
using namespace cv;
//-----------------------------------【全局函数声明部分】-----------------------------------
// 描述:全局函数声明
//-----------------------------------------------------------------------------------------------
void colorReduce(Mat& inputImage, Mat& outputImage, int div);
//--------------------------------------【main( )函数】---------------------------------------
// 描述:控制台应用程序的入口函数,我们的程序从这里开始执行
//-----------------------------------------------------------------------------------------------
int main()
{
//【1】创建原始图并显示
Mat srcImage = imread("C:/Users/Administrator/Desktop/OpenCV/1.jpg");
imshow("原始图像", srcImage);
//【2】按原始图的参数规格来创建创建效果图
Mat dstImage;
dstImage.create(srcImage.rows, srcImage.cols, srcImage.type());//效果图的大小、类型与原图片相同
//【3】记录起始时间
double time0 = static_cast<double>(getTickCount());
//【4】调用颜色空间缩减函数
colorReduce(srcImage, dstImage, 32);
//【5】计算运行时间并输出
time0 = ((double)getTickCount() - time0) / getTickFrequency();
cout << "\t此方法运行时间为: " << time0 << "秒" << endl; //输出运行时间
//【6】显示效果图
imshow("效果图", dstImage);
waitKey(0);
}
//---------------------------------【colorReduce( )函数】---------------------------------
// 描述:使用【指针访问:C操作符[ ]】方法版的颜色空间缩减函数
//----------------------------------------------------------------------------------------------
void colorReduce(Mat& inputImage, Mat& outputImage, int div)
{
//参数准备
outputImage = inputImage.clone(); //拷贝实参到临时变量
int rowNumber = outputImage.rows; //行数
int colNumber = outputImage.cols*outputImage.channels(); //列数 x 通道数=每一行元素的个数
//双重循环,遍历所有的像素值
for (int i = 0; i < rowNumber; i++) //行循环
{
uchar* data = outputImage.ptr<uchar>(i); //获取第i行的首地址
for (int j = 0; j < colNumber; j++) //列循环
{
// ---------【开始处理每个像素】-------------
data[j] = data[j] / div*div + div / 2;
// ----------【处理结束】---------------------
} //行处理结束
}
}
原图:
效果图:
2.用迭代器操作像素
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
using namespace std;
using namespace cv;
//-----------------------------------【全局函数声明部分】-----------------------------------
// 描述:全局函数声明
//-----------------------------------------------------------------------------------------------
void colorReduce(Mat& inputImage, Mat& outputImage, int div);
//--------------------------------------【main( )函数】--------------------------------------
// 描述:控制台应用程序的入口函数,我们的程序从这里开始执行
//-----------------------------------------------------------------------------------------------
int main()
{
//【1】创建原始图并显示
Mat srcImage = imread("C:/Users/Administrator/Desktop/OpenCV/1.jpg");
imshow("原始图像", srcImage);
//【2】按原始图的参数规格来创建创建效果图
Mat dstImage;
dstImage.create(srcImage.rows, srcImage.cols, srcImage.type());//效果图的大小、类型与原图片相同
//【3】记录起始时间
double time0 = static_cast<double>(getTickCount());
//【4】调用颜色空间缩减函数
colorReduce(srcImage, dstImage, 32);
//【5】计算运行时间并输出
time0 = ((double)getTickCount() - time0) / getTickFrequency();
cout << "此方法运行时间为: " << time0 << "秒" << endl; //输出运行时间
//【6】显示效果图
imshow("效果图", dstImage);
waitKey(0);
}
//-------------------------------------【colorReduce( )函数】-----------------------------
// 描述:使用【迭代器】方法版的颜色空间缩减函数
//----------------------------------------------------------------------------------------------
void colorReduce(Mat& inputImage, Mat& outputImage, int div)
{
//参数准备
outputImage = inputImage.clone(); //拷贝实参到临时变量
//获取迭代器
Mat_<Vec3b>::iterator it = outputImage.begin<Vec3b>(); //初始位置的迭代器
Mat_<Vec3b>::iterator itend = outputImage.end<Vec3b>(); //终止位置的迭代器
//存取彩色图像像素
for (; it != itend; ++it)
{
// ------------------------【开始处理每个像素】--------------------
(*it)[0] = (*it)[0] / div*div + div / 2;
(*it)[1] = (*it)[1] / div*div + div / 2;
(*it)[2] = (*it)[2] / div*div + div / 2;
// ------------------------【处理结束】----------------------------
}
}
Vec3b指BGR三个颜色通道,既是三个unsigned char组成的向量。
效果同1.
3.动态地址计算
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
using namespace std;
using namespace cv;
//-----------------------------------【全局函数声明部分】-----------------------------------
// 描述:全局函数声明
//-----------------------------------------------------------------------------------------------
void colorReduce(Mat& inputImage, Mat& outputImage, int div);
//--------------------------------------【main( )函数】--------------------------------------
// 描述:控制台应用程序的入口函数,我们的程序从这里开始执行
//-----------------------------------------------------------------------------------------------
int main()
{
//【1】创建原始图并显示
Mat srcImage = imread("C:/Users/Administrator/Desktop/OpenCV/1.jpg");
imshow("原始图像", srcImage);
//【2】按原始图的参数规格来创建创建效果图
Mat dstImage;
dstImage.create(srcImage.rows, srcImage.cols, srcImage.type());//效果图的大小、类型与原图片相同
//【3】记录起始时间
double time0 = static_cast<double>(getTickCount());
//【4】调用颜色空间缩减函数
colorReduce(srcImage, dstImage, 32);
//【5】计算运行时间并输出
time0 = ((double)getTickCount() - time0) / getTickFrequency();
cout << "此方法运行时间为: " << time0 << "秒" << endl; //输出运行时间
//【6】显示效果图
imshow("效果图", dstImage);
waitKey(0);
}
//-------------------------------------【colorReduce( )函数】-----------------------------
// 描述:使用【迭代器】方法版的颜色空间缩减函数
//----------------------------------------------------------------------------------------------
void colorReduce(Mat& inputImage, Mat& outputImage, int div)
{
//参数准备
outputImage = inputImage.clone(); //拷贝实参到临时变量
int rowNumber = outputImage.rows;
int colNumber = outputImage.cols;
//存取彩色图像像素
for (int i = 0; i < rowNumber; i++){
for (int j = 0; j < colNumber; j++){
outputImage.at<Vec3b>(i, j)[0] = outputImage.at<Vec3b>(i, j)[0] / div*div + div / 2;//Vec3b BGR,<Vec3b>(i, j)[0]指B,蓝色通道
outputImage.at<Vec3b>(i, j)[1] = outputImage.at<Vec3b>(i, j)[1] / div*div + div / 2;//绿色通道
outputImage.at<Vec3b>(i, j)[2] = outputImage.at<Vec3b>(i, j)[2] / div*div + div / 2;//红色通道
}
}
}
效果同1.
4.初级图像混合
计算图像数组加权和的 addWeighted()函数,下面代码实现了感兴趣区域 ROI 与图像线性混合操作。
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
using namespace cv;
using namespace std;
//-----------------------------------【全局函数声明部分】--------------------------------------
// 描述:全局函数声明
//-----------------------------------------------------------------------------------------------
bool ROI_AddImage();
bool LinearBlending();
bool ROI_LinearBlending();
//-----------------------------------【main( )函数】--------------------------------------------
// 描述:控制台应用程序的入口函数,我们的程序从这里开始
//-----------------------------------------------------------------------------------------------
int main( )
{
system("color 6F");
if(ROI_AddImage( )&& LinearBlending( )&&ROI_LinearBlending( ))
{
cout<<endl<<"\n运行成功,得出了需要的图像";
}
waitKey(0);
return 0;
}
//----------------------------------【ROI_AddImage( )函数】----------------------------------
// 函数名:ROI_AddImage()
// 描述:利用感兴趣区域ROI实现图像叠加
//----------------------------------------------------------------------------------------------
bool ROI_AddImage()
{
// 【1】读入图像
Mat srcImage1= imread("D:/初级图像混合/dota_pa.jpg");
Mat logoImage= imread("D:/初级图像混合/dota_logo.jpg");
if( !srcImage1.data ) { printf("读取srcImage1错误~! \n"); return false; }
if( !logoImage.data ) { printf("读取logoImage错误~! \n"); return false; }
// 【2】定义一个Mat类型并给其设定ROI区域
Mat imageROI= srcImage1(Rect(200,250,logoImage.cols,logoImage.rows));
// 【3】加载掩模(必须是灰度图)
Mat mask= imread("dota_logo.jpg",0);
//【4】将掩膜拷贝到ROI
logoImage.copyTo(imageROI,mask);
// 【5】显示结果
namedWindow("<1>利用ROI实现图像叠加示例窗口");
imshow("<1>利用ROI实现图像叠加示例窗口",srcImage1);
return true;
}
//---------------------------------【LinearBlending()函数】-------------------------------------
// 函数名:LinearBlending()
// 描述:利用cv::addWeighted()函数实现图像线性混合
//--------------------------------------------------------------------------------------------
bool LinearBlending()
{
//【0】定义一些局部变量
double alphaValue = 0.5;
double betaValue;
Mat srcImage2, srcImage3, dstImage;
// 【1】读取图像 ( 两幅图片需为同样的类型和尺寸 )
srcImage2 = imread("D:/初级图像混合/mogu.jpg");
srcImage3 = imread("D:/初级图像混合/rain.jpg");
if( !srcImage2.data ) { printf("读取srcImage2错误! \n"); return false; }
if( !srcImage3.data ) { printf("读取srcImage3错误! \n"); return false; }
// 【2】进行图像混合加权操作
betaValue = ( 1.0 - alphaValue );
addWeighted( srcImage2, alphaValue, srcImage3, betaValue, 0.0, dstImage);
// 【3】显示原图窗口
imshow( "<2>线性混合示例窗口【原图】", srcImage2 );
imshow( "<3>线性混合示例窗口【效果图】", dstImage );
return true;
}
//---------------------------------【ROI_LinearBlending()】-------------------------------------
// 函数名:ROI_LinearBlending()
// 描述:线性混合实现函数,指定区域线性图像混合.利用cv::addWeighted()函数结合定义
// 感兴趣区域ROI,实现自定义区域的线性混合
//--------------------------------------------------------------------------------------------
bool ROI_LinearBlending()
{
//【1】读取图像
Mat srcImage4= imread("D:/初级图像混合/dota_pa.jpg",1);//参数1表示返回彩色,0表示返回灰度,参见书本第66页
Mat logoImage= imread("D:/初级图像混合/初级图像混合/dota_logo.jpg");
if( !srcImage4.data ) { printf("读取srcImage4错误~! \n"); return false; }
if( !logoImage.data ) { printf("读取logoImage错误~! \n"); return false; }
//【2】定义一个Mat类型并给其设定ROI区域
Mat imageROI;
//方法一
imageROI= srcImage4(Rect(200,250,logoImage.cols,logoImage.rows));
//方法二
//imageROI= srcImage4(Range(250,250+logoImage.rows),Range(200,200+logoImage.cols));
//【3】将logo加到原图上
addWeighted(imageROI,0.5,logoImage,0.3,0.,imageROI);
//【4】显示结果
imshow("<4>区域线性图像混合示例窗口",srcImage4);
return true;
}
这里仅选取LinearBounding 部分图像。
原图:
效果图:
5.多通道图像混合
#include<opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<iostream>
using namespace std;
using namespace cv;
//声明全局函数
bool MultiChannelBlending();
int main(){
system("color 9F");
if (MultiChannelBlending()){
cout << "运行成功。取得了需要的图像~!";
}
waitKey(0);
return 0;
}
bool MultiChannelBlending(){
Mat srcImage;
Mat logoImage;
vector<Mat>channels;
Mat imageBlueChannel;
//=================【蓝色通道部分】=================
// 描述:多通道混合-蓝色分量部分
//============================================
// 【1】读入图片
logoImage = imread("dota_logo.jpg", 0);//将logo图像灰度化
//imshow("111", logoImage);
srcImage = imread("dota_jugg.jpg");
if (!logoImage.data) { printf("Oh,no,读取logoImage错误~! \n"); return false; }
if (!srcImage.data) { printf("Oh,no,读取srcImage错误~! \n"); return false; }
//【2】把一个3通道图像转换成3个单通道图像
split(srcImage, channels);//分离色彩通道
//【3】将原图的蓝色通道引用返回给imageBlueChannel,注意是引用,相当于两者等价,修改其中一个另一个跟着变
imageBlueChannel = channels.at(0);
//imshow("222", imageBlueChannel);
//【4】将原图的蓝色通道的(500,250)坐标处右下方的一块区域和logo图进行加权操作,将得到的混合结果存到imageBlueChannel中
addWeighted(imageBlueChannel(Rect(500, 250, logoImage.cols, logoImage.rows)), 1.0,
logoImage, 0.5, 0, imageBlueChannel(Rect(500, 250, logoImage.cols, logoImage.rows)));
//【5】将三个单通道重新合并成一个三通道
merge(channels, srcImage);
//【6】显示效果图
namedWindow(" <1>游戏原画+logo蓝色通道");
imshow(" <1>游戏原画+logo蓝色通道", srcImage);
imwrite("蓝色效果图.jpg", srcImage);
//=================【绿色通道部分】=================
// 描述:多通道混合-绿色分量部分
//============================================
//【0】定义相关变量
Mat imageGreenChannel;
//【1】重新读入图片
logoImage = imread("dota_logo.jpg", 0);
srcImage = imread("dota_jugg.jpg");
if (!logoImage.data) { printf("读取logoImage错误~! \n"); return false; }
if (!srcImage.data) { printf("读取srcImage错误~! \n"); return false; }
//【2】将一个三通道图像转换成三个单通道图像
split(srcImage, channels);//分离色彩通道
//【3】将原图的绿色通道的引用返回给imageBlueChannel,注意是引用,相当于两者等价,修改其中一个另一个跟着变
imageGreenChannel = channels.at(1);
//【4】将原图的绿色通道的(500,250)坐标处右下方的一块区域和logo图进行加权操作,将得到的混合结果存到imageGreenChannel中
addWeighted(imageGreenChannel(Rect(500, 250, logoImage.cols, logoImage.rows)), 1.0,
logoImage, 0.5, 0., imageGreenChannel(Rect(500, 250, logoImage.cols, logoImage.rows)));
//【5】将三个独立的单通道重新合并成一个三通道
merge(channels, srcImage);
//【6】显示效果图
namedWindow("<2>游戏原画+logo绿色通道");
imshow("<2>游戏原画+logo绿色通道", srcImage);
imwrite("绿色效果图.jpg", srcImage);
//=================【红色通道部分】=================
// 描述:多通道混合-红色分量部分
//============================================
//【0】定义相关变量
Mat imageRedChannel;
//【1】重新读入图片
logoImage = imread("dota_logo.jpg", 0);
srcImage = imread("dota_jugg.jpg");
if (!logoImage.data) { printf("Oh,no,读取logoImage错误~! \n"); return false; }
if (!srcImage.data) { printf("Oh,no,读取srcImage错误~! \n"); return false; }
//【2】将一个三通道图像转换成三个单通道图像
split(srcImage, channels);//分离色彩通道
//【3】将原图的红色通道引用返回给imageBlueChannel,注意是引用,相当于两者等价,修改其中一个另一个跟着变
imageRedChannel = channels.at(2);
//【4】将原图的红色通道的(500,250)坐标处右下方的一块区域和logo图进行加权操作,将得到的混合结果存到imageRedChannel中
addWeighted(imageRedChannel(Rect(500, 250, logoImage.cols, logoImage.rows)), 1.0,
logoImage, 0.5, 0., imageRedChannel(Rect(500, 250, logoImage.cols, logoImage.rows)));
//【5】将三个独立的单通道重新合并成一个三通道
merge(channels, srcImage);
//【6】显示效果图
namedWindow("<3>游戏原画+logo红色通道 ");
imshow("<3>游戏原画+logo红色通道 ", srcImage);
imwrite("红色效果图.jpg", srcImage);
return true;
}
原图:
效果图(选取蓝色通道部分):