opencv图像处理基础 (《OpenCV编程入门--毛星云》学习笔记一---五章)
#include <QCoreApplication>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp> using namespace cv; int main()
{
Mat Valley = imread("/home/ttwang/Valley.jpg");
Mat ValleyLogo = imread("/home/ttwang/ValleyLogo.jpg");
namedWindow("[1] ValleyPic");
imshow("[1] ValleyPic",Valley);
namedWindow("[2] ValleyLogo");
imshow("[2] ValleyLogo",ValleyLogo);
Mat valleyROI;
/******************实现两个图像混合****************************/
valleyROI = Valley(Rect(,,ValleyLogo.cols,ValleyLogo.rows));
addWeighted(valleyROI,0.5,ValleyLogo,0.3,.,valleyROI);
namedWindow("valley+logo");
imshow("valley+logo",Valley);
// imwrite("",Valley);
waitKey();
return ; }
二、创建滑动条:createTrackbar()函数 (利用滑动条实现两幅图的Alpha混合)
#include <QCoreApplication> //本人所用的IDE是QT,,终端编译时不需要该声明
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
using namespace cv; #define WINDOW_NAME "[Alpha]" //窗口名的宏定义 const int g_nMaxAlphaValue = ;
int g_nAlphaValueSlider;
double g_dAlphaValue;
double g_dBetaValue; Mat g_srcImage1;
Mat g_srcImage2;
Mat g_dstImage;
/**********响应滑动条的回调函数*************/
void on_Trackbar( int ,void*)
{
g_dAlphaValue = (double) g_nAlphaValueSlider/g_nMaxAlphaValue;
g_dBetaValue = (1.0 - g_dAlphaValue);
//根据Alpha beta的值进行线性混合
addWeighted(g_srcImage1,g_dAlphaValue,g_srcImage2,g_dBetaValue,0.0,g_dstImage);
imshow(WINDOW_NAME,g_dstImage);
} int main()
{
g_srcImage1 = imread("/home/ttwang/11.jpg"); //两幅图的尺寸要相同,否则出现如下图错误
g_srcImage2 = imread("/home/ttwang/12.jpg"); g_nAlphaValueSlider = ;
namedWindow(WINDOW_NAME,); char TrackbarName[];
sprintf(TrackbarName,"透明值 %d", g_nMaxAlphaValue);
createTrackbar(TrackbarName,WINDOW_NAME, &g_nAlphaValueSlider, g_nMaxAlphaValue,on_Trackbar);
on_Trackbar(g_nAlphaValueSlider,); waitKey();
return ; }
由于程序不是直接粘贴过来的,按该程序进行编译时候,总出现错误,可以参考下面的链接感谢分享
三、鼠标操作:SetMouseCallback()函数
#include <QCoreApplication>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
using namespace cv; #define WINDOW_NAME "[Program window]" //为窗口标题定义的宏 /******************全局函数的声明********************/
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(); int main()
{
g_rectangle = Rect(-,-,,);
Mat srcImage(,,CV_8UC3),tempImage;
srcImage.copyTo(tempImage);
g_rectangle = Rect(-,-,,);
srcImage = Scalar::all(); //设置鼠标操作回调函数
namedWindow(WINDOW_NAME);
setMouseCallback(WINDOW_NAME,on_MouseHandle,(void*)&srcImage);
while()
{
srcImage.copyTo(tempImage); //复制源图到临时变量
if(g_bDrawingBox) DrawRectangle(tempImage,g_rectangle);//当绘制标识符为真,进行绘制
imshow(WINDOW_NAME,tempImage);
if(waitKey() == ) break; //按下Esc,程序退出
}
return ;
} /*********鼠标回调函数,根据不同的鼠标事件进行不同的操作*******************/
void on_MouseHandle(int event, int x, int y, int flags, void *param)
{
Mat& image = *(cv::Mat*) param;
switch (event)
{
//鼠标移动消息
case EVENT_MOUSEMOVE:
{
if(g_bDrawingBox)//如果是否进行绘制额标识符为真,则记录下长和宽到RECT型变量中
{
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,,);//记录起始点
}
break;
//左键抬起消息
case EVENT_LBUTTONUP:
{
g_bDrawingBox = false; //置标识符为false
//对宽和高小于0的进行处理
if(g_rectangle.width < )
{
g_rectangle.x += g_rectangle.width;
g_rectangle.width *= -;
}
if(g_rectangle.height < )
{
g_rectangle.y += g_rectangle.height;
g_rectangle.height *= -;
}
//调用回调函数进行绘制
DrawRectangle( image, g_rectangle);
}
break; }
} /********************自定义的矩形绘制函数DrawRectangle() ********************/
void DrawRectangle(cv::Mat& img, cv::Rect box)
{
rectangle(img,box.tl(),box.br(),Scalar(g_rng.uniform(,),g_rng.uniform(,),g_rng.uniform(,)));
}
四章、OpenCV数据结构与基本绘图
1. Mat M(2,2,CV_8UC3,Scalar(0,0,255)); //使用Mat()构造函数创建Mat对象
两行两列、CV_8UC3: CV_[位数][带符号与否]C[通道数] Scalar是个short类型的向量,可以使用指定的值来初始化矩阵
2.Mat M; M.create(4,4,CV_8UC3); //使用create()函数创建Mat对象,,此方法不能为矩阵设初值
3.颜色的表示类:Scalar()是具有四个元素的数组,,第四个用不到,则不写 格式如下:
Scalar(a, b, c)定义的RGB颜色值:红色分量c 绿色分量b 蓝色分量 a
4.尺寸的表示类: Size() 常用格式: Size(5,5)表示构造出的Size高度和宽度都为5
5.矩形的表示类: Rect类的成员有x,y,width,height,分别为左上角的坐标和矩形的宽、高
格式: Rect rect(0,0,200,400)
6.颜色空间转换:cvtColor()函数 格式:cvtColor(InputArraysrc, OutputArray dst, int code, int dstCn=0)
第一个参数:输入图像;
第二个参数:输出图像;
第三个参数:颜色空间转换的标识符; (详见:P98)
第四个参数:目标图像的通道数,若为0,则表示其取源图像的通道数。
7.基本图型的绘制涉及的函数: (通过例程学习 P100)
绘制直线的line函数
绘制椭圆的ellipse函数
绘制矩形的rectangle函数
绘制圆的circle函数
绘制填充的多边形的fillPloy函数
第五章 core组件进阶
1.计时函数: getTickCount()和getTickFrequency()
getTickCount()函数返回CPU自某个事件以来走过的时钟周期数
getTickFrequency()函数返回CPU一秒钟走过的周期数
显然: 二者结合可以实现对某种图像处理方法的计时
double time0 = static_cast<double>(getTickCount()); //记录起始时间 time0= ((double)getTickCount() - time0)/getTickFrequency();////计算运行时间并输出 cout<<"\t此方法运行时间为:"<<time0<<"秒"<<endl; //输出运行时间
2.访问图像中像素的几种方法 (简单介绍,具体P110)
需要先明白以下知识:
(1) Mat类的公有成员变量cols和rows给出了图像的宽和高
image.cols image.rows
(2) Mat类的成员函数channels()用于返回图像的通道数;
灰度图像通道数1,彩色图像通道数为3 image.channels()
(4) 每一行的像素个数= image.cols*image.channels()
a.直接遍历,使用Mat里的成员函数data
/*********只用于访问连续空间********/
Mat mat (,,CV_8UC3)
int es = mat.eleSize(); //定义步长,因为定义为3通道的,实质该值为3
int size = mat.rows*mat.cols*es;
for(int i = ; i < size; i += es)
{
mat.data[i] = ; // B通道
mat.data[i+] = ; // G通道
mat.data[i+] = ; // R通道
}
b.直接访问不连续空间
for (int row = ; row < mat.rows; row++)
{
for (int col = ; col < mat.cols; col++)
{
(&mat.data[row*mat.step])[col*es] = ;
(&mat.data[row*mat.step])[col*es + ] = ;
(&mat.data[row*mat.step])[col*es + ] = ;
}
}
c.通过opencv ptr模板函数遍历
for (int row = ; row < mat.rows; row++)
{
for (int col = ; col < mat.cols; col++)
{
Vec3b *c = mat.ptr<Vec3b>(row,col);
c->val[] = ;
8 c->val[] = ;
10 c->val[] = ;
}
}
c.通过at遍历
for (int row = ; row < mat.rows; row++)
{
for (int col = ; col < mat.cols; col++)
{
Vec3b &m = mat.at<Vec3b>(row, col);
m[] = ;
m[] = ;
m[] = ;
}
}
d.通过迭代器遍历
auto it = mat.begin<Vec3b>(); //自动类型匹配auto
auto it_end = mat.end<Vec3b>();
for (; it != it_end; it++)
{
(*it).val[] = ;
(*it).val[] = ;
(*it).val[] = ;
}
.感兴趣区域ROI /******表示方法一 Rect矩形区域*******/ Mat imageROI
imageROI = image(Rect(,,logo.cols,logo.rows)); //image为已经载入好的图片 /******表示方法二 Range指定感兴趣的行和列********/ imageROI = image(Range(250,250+logoImage.rows),Range(200,200+logoImage.cols)); //image为已经载入好的图片
.利用addWeighted可实现图像线性混合
数学公式: dst = src1[I] * alpha + src2[I]*beta + gamma (P117)
.分离颜色通道、多通道图像混合
通道分离:split()函数,将一个3通道图像转换成3个单通道
通道合并:merge()函数 ###例程:(课本P127,以多通道混合-蓝色分量部分为例)
###平台:QT5.7.1+OpenCV3.2.0
###时间:2017年12月11日 /********建立QT控制台程序*********/
#include <QCoreApplication>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>
using namespace std;
using namespace cv; //全局函数声明
bool MultiChannelBlending(); int main()
{
if(MultiChannelBlending())
{
cout << endl << "\n运行成功,得到目标图像" << endl;
}
waitKey();
return ;
}
/*********多通道混合的实现函数*********/
bool MultiChannelBlending()
{
Mat srcImage;
Mat logoImage;
vector<Mat> channels;
/********** 蓝色分量 *************/
Mat imageBlueChannel;
logoImage = imread("/home/ttwang/Valley_logo.jpg",);//一定要读入会灰度图像,不然addWeighted()会因为类型不匹配而报错
srcImage = imread("/home/ttwang/Valley.jpg");
split(srcImage,channels); //将一个3通道图像转换成3个单通道
imageBlueChannel = channels.at(); //将原图的蓝色通道引用返回给imageBlueChannel
addWeighted(imageBlueChannel(Rect(,,logoImage.cols,logoImage.rows)),1.0,logoImage,0.5,.,imageBlueChannel(Rect(,,logoImage.cols,logoImage.rows)));
merge(channels,srcImage);//将三个单通道重新合并成一个三通道
namedWindow("src+LogoBlue");
imshow("src+LogoBlue",srcImage); /*******绿色分量 ******/
Mat imageGreenChannel;
logoImage = imread("/home/ttwang/Valley_logo.jpg",);
srcImage = imread("/home/ttwang/Valley.jpg");
split(srcImage,channels); //将一个3通道图像转换成3个单通道
imageGreenChannel = channels.at();
addWeighted(imageGreenChannel(Rect(,,logoImage.cols,logoImage.rows)),1.0,logoImage,0.5,0.0,imageGreenChannel(Rect(,,logoImage.cols,logoImage.rows)));
merge(channels,srcImage);//将三个单通道重新合并成一个三通道
namedWindow("src+LogoGreen");
imshow("src+LogoGreen",srcImage); /*******红色分量 ******/
Mat imageRedChannel;
logoImage = imread("/home/ttwang/Valley_logo.jpg",);
srcImage = imread("/home/ttwang/Valley.jpg");
split(srcImage,channels); //将一个3通道图像转换成3个单通道
imageRedChannel = channels.at();
addWeighted(imageRedChannel(Rect(,,logoImage.cols,logoImage.rows)),1.0,logoImage,0.5,0.0,imageRedChannel(Rect(,,logoImage.cols,logoImage.rows)));
merge(channels,srcImage);//将三个单通道重新合并成一个三通道
namedWindow("src+LogoRed");
imshow("src+LogoRed",srcImage);
return true;
}
.图像对比度、亮度调整 公式: g(i,j)=a*f(i,j)+b; (opencv控制图像对比度和亮度的理论公式) 参数a(a>)通常被成为增益,控制图像的对比度
参数b称为偏置,控制图像的亮度 访问图片中的像素:(使用三个for循环,语法:image.at<Vec3b>(y,x)[c])
其中,y是像素所在的行,x是像素所在的列,c是B、G、 R(对应0、、)
.离散傅里叶变换(详细参照课本P135)
参考资料及函数说明,参照下面的链接: opencv2教程之离散型傅里叶变换
opencv图像处理基础 (《OpenCV编程入门--毛星云》学习笔记一---五章)的更多相关文章
- 《Java核心技术·卷Ⅰ:基础知识(原版10》学习笔记 第5章 继承
<Java核心技术·卷Ⅰ:基础知识(原版10>学习笔记 第5章 继承 目录 <Java核心技术·卷Ⅰ:基础知识(原版10>学习笔记 第5章 继承 5.1 类.超类和子类 5.1 ...
- 《Jave并发编程的艺术》学习笔记(1-2章)
Jave并发的艺术 并发编程的挑战 上下文切换 CPU通过时间片分配算法来循环执行任务,当前时间片执行完之后会切换到下一个任务.但是,切换会保存上一个任务的状态,一遍下次切换回这个任务时,可以再次加载 ...
- 《Python基础教程(第二版)》学习笔记 -> 第五章 条件、循环 和 其他语句
条件和条件语句 下面的值在作为布尔表达式的时候,会被解释器看作假(False):False None 0 "" () [] {} 条件执行和if语句 ...
- c#高级编程第七版 学习笔记 第三章 对象和类型
第三章 对象和类型 本章的内容: 类和结构的区别 类成员 按值和按引用传送参数 方法重载 构造函数和静态构造函数 只读字段 部分类 静态类 Object类,其他类型都从该类派生而来 3.1 类和结构 ...
- Dubbo入门到精通学习笔记(五):持续集成管理平台之sonarqube代码质量管理平台的介绍与安装
文章目录 SonarQube的介绍 SonarQube的安装 安装简介 详细安装过程 详细使用过程 SonarQube的介绍 SonarQube是一个管理代码质量的开放平台. 可以从七个维度检测代码质 ...
- 小甲鱼零基础汇编语言学习笔记第五章之[BX]和loop指令
这一章主要介绍什么是[BX]以及loop(循环)指令怎么使用,loop和[BX]又怎么样相结合,段前缀又是什么鬼,以及如何使用段前缀. 1.[BX]的概念 [BX]和[0]类似 ...
- opencv学习笔记(五)镜像对称
opencv学习笔记(五)镜像对称 设图像的宽度为width,长度为height.(x,y)为变换后的坐标,(x0,y0)为原图像的坐标. 水平镜像变换: 代码实现: #include <ios ...
- 《零基础学JavaScript(全彩版)》学习笔记
<零基础学JavaScript(全彩版)>学习笔记 二〇一九年二月九日星期六0时9分 前期: 刚刚学完<零基础学HTML5+CSS3(全彩版)>,准备开始学习JavaScrip ...
- 《C#并发编程经典实例》学习笔记—2.7 避免上下文延续
避免上下文延续 在默认情况下,一个 async 方法在被 await 调用后恢复运行时,会在原来的上下文中运行. 为了避免在上下文中恢复运行,可让 await 调用 ConfigureAwait 方法 ...
随机推荐
- SVN图形客户端上传静态库.a文件失败
1.原因客户端未添加静态库 2.解决办法 到项目静态库所在目录用命令行添加静态库文件 svn add ****.a 3.可能存在问题 Mac OS的自带SVN版本过低不能添加,报错如下: svn: E ...
- cobbler 自定义安装系统
1.自定义安装系统(根据mac地址)--name=定义名称--mac=客户端的mac地址--ip-address=需求的ip--subnet=掩码 --gateway=网关--interface=网口 ...
- c++之sleep函数
c++之sleep函数 c++中使用sleep函数需要导入第三方库,标准库中没有该函数实现. 我们导入window.h使用Sleep()方法,注意:第一个S要大写,括号中的表示的整数倍的毫秒 Slee ...
- Java抽象工厂模式
Java抽象工厂模式 基本定义 抽象工厂模式是所有形态的工厂模式中最为抽象和最其一般性的.抽象工厂模式可以向客户端提供一个接口,使得客户端在不必指定产品的具体类型的情况下,能够创建多个产品族的产品对象 ...
- Backing Up and Restoring HBase Data
There are two strategies for backing up HBase:1> Backing it up with a full cluster shutdown2> ...
- 获取设备信息——获取客户端ip地址和mac地址
1.获取本地IP(有可能是 内网IP,192.168.xxx.xxx) /** * 获取本地IP * * @return */ public static String getLocalIpAddre ...
- hbase集群中其中某个regionserver 没有启动
第一步: date命令查看各个机器的时间 发现linux02机器时间差了2个多小时 第二步:ntpdate pool.ntp.org 修改错误时间的机器 第三步: 重启 hbase
- JVM-压缩指针
什么是压缩指针: 通常64位JVM消耗的内存会比32位的最多会多用1.5倍,这是因为对象指针在64位架构下,对象指针长度会翻倍. 对于那些将要从32位平台移植到64位的应用来说,平白无辜多了1/2的内 ...
- 【数组】Game of Life
题目: According to the Wikipedia's article: "The Game of Life, also known simply as Life, is a ce ...
- 图解安卓-c++开发-通过java 调用c++ jni的使用
接着上一节 ,很多事情用java做,效率要差一点(尤其是游戏),所以要用c++来实现,那么java如何调用c++ 首先建议一个工程 HelloJni如下图: 按照默认的配置下一步,直到完成 . 如下图 ...