//__________加载图片______________
// 注意imread的第二个参数intflag默认是1,即原色彩,但是他可以指定多种色彩,比如0即灰色,一个彩色的图载入进去就会变成灰色
// CV_LOAD_IMAGE_UNCHANGED = -1,// 此值已被废弃
// CV_LOAD_IMAGE_GRAYSCALE = 0,// 灰度(灰色、黑白)
// CV_LOAD_IMAGE_COLOR = 1,// 彩色
// CV_LOAD_IMAGE_ANYDEPTH,// 深度返回?
// 一个彩色可以变成灰色,一个灰色却不能变为彩色
Mat srcImage = imread("1_5_12.jpg",0);// 图片文件放在debug/release文件夹同级
namedWindow("【原始图】");
imshow("【原始图】",srcImage);
waitKey(0);
//_________图像腐蚀_______________
Mat srcImage = imread("1_5_2.jpg");// 加载图片
namedWindow("【原图】腐蚀操作");// 窗口
imshow("【原图】腐蚀操作",srcImage);// 显示原图
Mat element = getStructuringElement(MORPH_RECT,Size(15,15));// 进行腐蚀操作
Mat dstImage;
erode(srcImage,dstImage,element);
namedWindow("【效果图】腐蚀操作");
imshow("【效果图】腐蚀操作",dstImage);// 显示效果图
waitKey(0);
//______________图像模糊____________
Mat srcImage = imread("1_5_3.jpg");
namedWindow("均值滤波【原图】");
imshow("均值滤波【原图】",srcImage);
Mat dstImage;
blur(srcImage,dstImage,Size(7,7));
namedWindow("均值滤波【效果图】");
imshow("均值滤波【效果图】",dstImage);
waitKey(0);
//_____________边缘检测____________
Mat srcImage = imread("1_5_4.jpg");
namedWindow("【原始图】Canny边缘检测");
imshow("【原始图】Canny边缘检测",srcImage);
Mat dstImage,edge,grayImage;
dstImage.create(srcImage.size(),srcImage.type());// 创建和src同样类型和大小的矩阵
cvtColor(srcImage,grayImage,CV_BGR2GRAY);// opencv3:COLOR_BGR2GRAY;opencv2:CV_BGR2GRAY
blur(grayImage,edge,Size(3,3));// 先使用3*3内核来降噪
Canny(edge,edge,3,9,3);// 运行Canny算子
namedWindow("【效果图】Canny边缘检测");
imshow("【效果图】Canny边缘检测",edge);
waitKey(0);
//_____________读取视频___________________
VideoCapture capture("1_6_1.avi");// 读取视频
namedWindow("读取视频");
while(1)
{
Mat frame;
capture>>frame;// 读取当前帧
imshow("读取视频",frame);// 显示当前帧
waitKey(30);
}
//______________调用摄像头_____________
VideoCapture capture(0);
namedWindow("读取视频");
while(1)
{
Mat frame;
capture>>frame;
imshow("读取视频",frame);
waitKey(30);
}
//______________摄像头边缘检测_____________
VideoCapture capture(0);
Mat edges;
namedWindow("被canny后的视频");
while(1)
{
Mat frame;
capture>>frame;
cvtColor(frame,edges,COLOR_BGR2GRAY);
blur(edges,edges,Size(7,7));
Canny(edges,edges,0,30,3);
imshow("被canny后的视频",edges);
waitKey(30);
}
//_____________用imwrite输出png___________________
Mat mat(480,640,CV_8UC4);// 创建带alpha通道的Mat
createAlphaMat(mat);
vector compression_params;
compression_params.push_back(IMWRITE_PNG_COMPRESSION);
compression_params.push_back(9);
try
{
namedWindow("透明Alpha值图");
imwrite("透明Alpha值图",mat,compression_params);// imwrite测试失败,不知原因
namedWindow("生成的PNG图");
imshow("生成的PNG图",mat);
fprintf(stdout,"PNG图片文件的alpha数据保存完毕~\n可以在工程目录下查看由imwrite函数生成的图片\n");
waitKey(0);
}
catch(runtime_error & ex)
{
fprintf(stderr,"图像转换成PNG格式发生错误:%s\n",ex.what());
return 1;
}
void createAlphaMat(Mat & mat)
{
for(int i = 0;i(i,j);
rgba[0] = UCHAR_MAX;
rgba[1] = saturate_cast((float(mat.cols-j))/((float)mat.rows)*UCHAR_MAX);
rgba[2] = saturate_cast((float(mat.rows-i))/((float)mat.rows)*UCHAR_MAX);
rgba[3] = saturate_cast(0.5*(rgba[1]+rgba[2]));
}
}
}
#include "study3_1_9.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace cv;
using namespace std;
Study3_1_9::Study3_1_9()
{
//___________载入和显示____________
Mat girl = imread("girl.jpg");
namedWindow("【1】动漫图");
imshow("【1】动漫图",girl);
//___________初级图像混合__________
Mat image = imread("dota.jpg");
Mat logo = imread("dota_logo.jpg");
qDebug()<<"image-cols:"<
Mat image("xxx.jpg");
Mat imageROI = image(Rect(x,y,width,height));//在image内指定一个矩形,指定矩形的起点以及宽和高
Mat imageROI = image(Range(x1,xn),Range(y1,yn));// 或者指定一个x坐标的起止点(序列),指定一个y坐标的起止点(序列)
// 需要注意的是,不管是哪种方法,范围内所有点必须在image范围之内
// 资源1,alpha,资源2,alpha,偏差,输出
addWeighted(imageROI,0.1,logo,0.1,0,imageROI);// 图片融合,就是刚才切出来的图和要贴上去的图做一个融合
// 注意修改了imageROI其实也修改了image
注意:载入的两个图片必须一样大小。
下面的示例来自于:http://monkeycoding.com/?p=652,感谢!
#include
#include
using namespace cv;
int sliderValue;
Mat src1, src2;
void on_trackbar(int, void*){
double alpha = (double) sliderValue/100.0 ;
double beta = ( 1.0 - alpha );
Mat dst;
addWeighted( src1, alpha, src2, beta, 0.0, dst);
imshow("trackbar demo", dst);
}
int main(){
src1 = imread("beach.jpg",CV_LOAD_IMAGE_UNCHANGED);
src2 = imread("cat.jpg",CV_LOAD_IMAGE_UNCHANGED);
sliderValue = 0;
int sliderMaxValue = 100;
namedWindow("trackbar demo", 0);
createTrackbar("Ratio", "trackbar demo", &sliderValue, sliderMaxValue, on_trackbar);
on_trackbar(sliderValue, 0 );
waitKey(0);
return 0;
}
注意:窗口不要用宏定义+中文,不知道为什么就是出问题,改了就好了
#include
#include
using namespace cv;
// 全局函数声明
void on_MouseHandle(int event,int x,int y,int flags,void * param);
void DrawRectangle(cv::Mat& img,cv::Rect box);
void ShowHelpText();
// 全局变量声明
Rect g_rectangle;
bool g_bDrawingBox = false;
RNG g_rng(123456);
int main(int argc,char ** argv)
{
// 鼠标交互setMouseCallback
// 准备参数
g_rectangle = Rect(-1,-1,0,0);
Mat srcImage(600,800,CV_8UC3),tempImage;
srcImage.copyTo(tempImage);
g_rectangle = Rect(-1,-1,0,0);
srcImage = Scalar::all(0);
// 设置鼠标操作回调
namedWindow("testw");
setMouseCallback("testw",on_MouseHandle,(void*)&srcImage);
// 程序主循环,当进行绘制的标识符为真时,进行绘制
while(1)
{
srcImage.copyTo(tempImage);// 复制源图到临时变量
if(g_bDrawingBox)
DrawRectangle(tempImage,g_rectangle);// 当进行绘制的标识符为真时,则进行绘制
imshow("testw",tempImage);
if(waitKey(10)==27)
break;// 当按下esc,退出
}
return 0;
}
void on_MouseHandle(int event, int x, int y, int flags, void *param)
{
Mat & image = *(cv::Mat*) param;// 一个Mat类型的指针执行指针标识,就变成引用
switch(event)
{
case EVENT_MOUSEMOVE:
{
if(g_bDrawingBox)
{
g_rectangle.width = x-g_rectangle.x;
g_rectangle.height = y-g_rectangle.y;
}
}
break;
case EVENT_LBUTTONDOWN:
{
g_bDrawingBox = true;
g_rectangle = Rect(x,y,0,0);// 记录起始点
}
break;
case EVENT_LBUTTONUP:
{
g_bDrawingBox = false;
if(g_rectangle.width<0)
{
g_rectangle.x+=g_rectangle.width;
g_rectangle.width *= -1;//乘以-1
}
if(g_rectangle.height<0)
{
g_rectangle.y+=g_rectangle.height;
g_rectangle.height *= -1;
}
DrawRectangle(image,g_rectangle);
}
break;
}
}
void DrawRectangle(cv::Mat &img, Rect box)
{
rectangle(img,box.tl(),box.br(),Scalar(g_rng.uniform(0,255),g_rng.uniform(0,255),g_rng.uniform(0,255)));// 随机颜色
}
Mat A,C;// 仅创建信息头部分
A = imread("1.jpg",CV_LOAD_IMAAGE_COLOR);// 这里为矩阵开辟内存
Mat B(A);// 使用拷贝构造函数(指针指向同一个矩阵)
C = A;// 这里ABC都是指向同一个内存
// 以下两个方法都是共享矩阵(内存),而且指定了范围
Mat D(A,Rect(10,10,100,100));// 使用矩形界定
Mat E = A(Range:all(),Range(1,3));// 使用行列界定
// 使用clone和copyTo则完全复制,指向不同的内存
Mat F = A.clone();
Mat G;
A.copyTo(G);
(1)使用Mat()构造函数
Mat M(2,2,CV_8UC3,Scalar(0,0,255));
// 2,2即2行2列
// CV_8UC3公式:CV_[位数][带符号否][类型前缀][通道数]
// 8UC3即:使用8位的unsigned char型,每个像素由3个元素组成3通道
// Scalar是个short型的向量,可以用他表示一个颜色(即3通道)
// 输出:
cout<<"M="<
输出:
M=
[ 0, 0, 255, 0, 0, 255;
0, 0, 255, 0, 0, 255]
由此可见,Mat的矩阵就是:
[x,y,z,x,y,z,x,y,z;
x,y,z,x,y,z,x,y,z]
这样连起来,换行用分号。
(2)用create创建
Mat M;
M.create(4,4,CV_8UC2);
cout<<"M="<
[ 64, 210, 119, 98, 80, 210, 119, 98;
96, 210, 119, 98, 224, 207, 119, 98;
240, 207, 119, 98, 0, 208, 119, 98;
16, 208, 119, 98, 32, 208, 119, 98]
Mat r = Mat(10,3,CV_8UC3);
randu(r,Scalar::all(0),Scalar::all(255));
cout<<"r(PythonStyle)="<
r(PythonStyle)=[[[ 91, 2, 79], [179, 52, 205], [236, 8, 181]],
[[239, 26, 248], [207, 218, 45], [183, 158, 101]],
[[102, 18, 118], [ 68, 210, 139], [198, 207, 211]],
[[181, 162, 197], [191, 196, 40], [ 7, 243, 230]],
[[ 45, 6, 48], [173, 242, 125], [175, 90, 63]],
[[ 90, 22, 112], [221, 167, 224], [113, 208, 123]],
[[214, 35, 229], [ 6, 143, 138], [ 98, 81, 118]],
[[187, 167, 140], [218, 178, 23], [ 43, 133, 154]],
[[150, 76, 101], [ 8, 38, 238], [ 84, 47, 7]],
[[117, 246, 163], [237, 69, 129], [ 60, 101, 41]]]
颜色与RGB数值,数值越小,颜色越深;数值越大颜色越浅。
三个数值线性变化则颜色会呈明暗变化,但是色相基本不变。
// ______________颜色空间缩减原理________________
// 注意:此处颜色空间缩减,并非能减少图片在内存中占用空间的意思。
// 此处的意思是,如果我们需要把图片的所有点的数据取出来进行操作处理,如果我们用此缩减的方法,那么存放这些用来处理的数据可以更精简
// 此处非图片压缩之意,而是缩减我们的处理数据
// 颜色每个通道有0~255共256个数,由于数值相近则颜色非常相近,我们用近似取法,即:
// 0~9的数取0
// 10~19的数取10
// ...
// 这样做其实这个颜色偏差不大,但是数据量就少了很多
// 可以这样理解:颜色有256种,256种之间区别很精细。我们缩减到26种,就是颜色没有分的那么精细了,但是在某些情况下还是可用。
// 只要这样:颜色数值/10*10,就可以了比如136,136/10即13,余数6自动被丢弃,再乘以10,则变成130.
// 即我们只需要:0,10,20,30,40,50,60,70,80,90,100,110,120,130,140,150,160,170,180,190,200,210,220,230,240,250.
// 我们可以做一个这样的对应表:256个颜色给他分别对应到26个颜色里面,这样就不需要再计算了。
int divideWith = 10;
uchar table[256];
for(int i = 0;i<256;i++)
table[i] = divideWith*(i/divideWith);
// 注意这个table:
// table[0] = 0;
// table[1] = 0;
// table[2] = 0;
// table[3] = 0;
// ...
// table[10] = 10;
// table[11] = 10;
// table[12] = 10;
// ...
// table[20] = 20;
// table[21] = 20;
// ...
// ...
// table[250] = 250;
// table[251] = 250;
// table[252] = 250;
// ...
// 可见这个talbe已经天然的完成了一个映射关系,他的下标跟值的映射
// p[j] = table[p[j]];// 颜色值变成table的下标,取对应下标的值
// 用LUT函数
Mat lookUpTable(1,256,CV_8U);
uchar * p = lookUpTable.data;
for(int i = 0;i<256;i++)
p[i] = table[i];// 把数据装到p,改变了p其实也改变了lookUpTable
// 然后就可以用LUT函数了,
LUT(I输入图片Mat,lookUpTable,J输出图片Mat);// 直接全图全转了
#include
#include
#include
#include
#pragma execution_character_set("utf-8")
using namespace cv;
using namespace std;
void colorReduceByPointer(Mat & inputImage,Mat & outputImage,int div);
void colorReduceByIterator(Mat & inputImage,Mat & outputImage,int div);
void colorReduceByAddr(Mat & inputImage,Mat & outputImage,int div);
int main(int argc,char ** argv)
{
Mat srcImage = imread("dota.jpg");
namedWindow("原始图像");
imshow("原始图像",srcImage);
Mat dstImage;
dstImage.create(srcImage.rows,srcImage.cols,srcImage.type());// 大小类型要相同
double time0 = static_cast(getTickCount());
// colorReduce(srcImage,dstImage,32);
// colorReduceByIterator(srcImage,dstImage,32);
colorReduceByAddr(srcImage,dstImage,32);
time0 = ((double)getTickCount()-time0)/getTickFrequency();
cout<<"this method run time is:"<(i);//获取第i行首地址
if(i == 1)
{
cout<<"data[1]="<::iterator it = outputImage.begin();
Mat_::iterator itend = outputImage.end();
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;
}
}
//____________________动态地址计算_____________________
void colorReduceByAddr(Mat &inputImage, Mat &outputImage, int div)
{
outputImage = inputImage.clone();
int rowNumber = outputImage.rows;
int colNumber = outputImage.cols;
for(int i = 0;i(i,j)[0] = outputImage.at(i,j)[0]/div*div+div/2;
outputImage.at(i,j)[1] = outputImage.at(i,j)[1]/div*div+div/2;
outputImage.at(i,j)[2] = outputImage.at(i,j)[2]/div*div+div/2;
}
}
}
Mat srcImage1 = imread("dota_pa.jpg");
Mat logoImage = imread("dota_logo.jpg");
if(!srcImage1.data)
{
printf("read image1 error!");
return 0;
}
if(!logoImage.data)
{
printf("read image2 error!");
return 0;
}
Mat imageROI = srcImage1(Rect(200,50,logoImage.cols,logoImage.rows));
Mat mask = imread("dota_logo.jpg",1);// 加载掩膜,书上说必须是灰度图,经测试此参数任意值都是可以的,缺省也可以
logoImage.copyTo(imageROI);// 书上写:logoImage.copyTo(imageROI,mask);经测试可以不要mask
namedWindow("window1");
imshow("window1",srcImage1);
double alphaValue = 0.2;
double betaValue;
Mat srcImage2,srcImage3,dstImage;
srcImage2 = imread("mogu.jpg");
srcImage3 = imread("rain.jpg");
if(!srcImage2.data)
{
printf("load image2 error!");
return 0;
}
if(!srcImage3.data)
{
printf("load image3 error!");
return 0;
}
betaValue = (1.0 - alphaValue);
addWeighted(srcImage2,alphaValue,srcImage3,betaValue,0.0,dstImage);// 两个图片叠加并配置透明比重
namedWindow("原图",1);
imshow("原图",srcImage2);
namedWindow("效果图",1);
imshow("效果图",dstImage);
#include
#include
#include
#include
#pragma execution_character_set("utf-8")
using namespace cv;
using namespace std;
bool ROI_AddImage();
bool LinearBlending();
bool ROI_LinearBlending();
int main(int argc,char ** argv)
{
system("color 5E");
if(ROI_AddImage()&&LinearBlending()&&ROI_LinearBlending())
{
cout<
//--------------------------------------【程序说明】-------------------------------------------
// 程序说明:《OpenCV3编程入门》OpenCV2版书本配套示例程序26
// 程序描述:分离颜色通道&多通道图像混合
// 开发测试所用IDE版本:Visual Studio 2010
// 开发测试所用OpenCV版本: 3.0 beta
// 2014年11月 Created by @浅墨_毛星云
// 2014年12月 Revised by @浅墨_毛星云
//------------------------------------------------------------------------------------------------
//-----------------------------------【头文件包含部分】---------------------------------------
// 描述:包含程序所依赖的头文件
//------------------------------------------------------------------------------------------------
#include
#include
#include
//-----------------------------------【命名空间声明部分】---------------------------------------
// 描述:包含程序所使用的命名空间
//-------------------------------------------------------------------------------------------------
using namespace cv;
using namespace std;
//-----------------------------------【全局函数声明部分】--------------------------------------
// 描述:全局函数声明
//-----------------------------------------------------------------------------------------------
bool MultiChannelBlending();
void ShowHelpText();
//-----------------------------------【main( )函数】------------------------------------------
// 描述:控制台应用程序的入口函数,我们的程序从这里开始
//-----------------------------------------------------------------------------------------------
int main( )
{
system("color 9F");
ShowHelpText( );
if(MultiChannelBlending( ))
{
cout< channels;
Mat imageBlueChannel;
//=================【蓝色通道部分】=================
// 描述:多通道混合-蓝色分量部分
//============================================
// 【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】把一个3通道图像转换成3个单通道图像
split(srcImage,channels);//分离色彩通道
//【3】将原图的蓝色通道引用返回给imageBlueChannel,注意是引用,相当于两者等价,修改其中一个另一个跟着变
imageBlueChannel= channels.at(0);
//【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);
//=================【绿色通道部分】=================
// 描述:多通道混合-绿色分量部分
//============================================
//【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);
//=================【红色通道部分】=================
// 描述:多通道混合-红色分量部分
//============================================
//【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);
return true;
}