OpenCV学习(7.10)

图像腐蚀和膨胀:

 1 #include "stdafx.h"
 2 
 3 using namespace std;
 4 using namespace cv;
 5 
 6 int main()
 7 {
 8 Mat frame = imread("1.jpg");
 9 imshow("test", frame);
10 Mat element = getStructuringElement(MORPH_CROSS, Size(15, 15));
11 Mat A;
12 erode(frame, A, element);
13 imshow("腐蚀图",A);
14 Mat B;
15 dilate(frame, B, element);
16 imshow("膨胀图",B);
17 waitKey(0);
18 
19 return 0;
20 }

getStructuringElement函数会返回指定形状和尺寸的结构元素。
这个函数的第一个参数表示内核的形状,有三种形状可以选择。
矩形:MORPH_RECT;
交叉形:MORPH_CORSS;
椭圆形:MORPH_ELLIPSE;
第二和第三个参数分别是内核的尺寸以及锚点的位置。一般在调用erode以及dilate函数之前,先定义一个Mat类型的变量来获得
getStructuringElement函数的返回值。对于锚点的位置,有默认值Point(-1,-1),表示锚点位于中心点。element形状唯一依赖锚点位置,

模糊和膨胀可以理解为一对滤波行为,也称为形态学滤波。滤波中用到的滤波器(kernal),在形态学中称为结构元素,往往由一个特殊的形状构成,如线条、矩形、圆等。
OpenCV中的erode和dilate函数支持多通道,各个通道处理过程独立。
腐蚀即求局部最小值的操作,图像A与核B作卷积运算,计算核B覆盖区域的像素点的最小值,并把这个值赋值给锚点(anchor point)指定的像素。
膨胀即求局部最大值的操作。
简单来说,膨胀会让图片中高亮度区域变得更大,腐蚀会让图片中低亮度区域变得更大(数学知识的缺乏让我只能感性认识,不过似乎够了……)

图像模糊:

 1 #include "stdafx.h"
 2 
 3 using namespace std;
 4 using namespace cv;
 5 
 6 int main()
 7 {
 8 Mat frame = imread("1.jpg");
 9 imshow("原图", frame);
10 
11 Mat A;
12 blur(frame, A, Size(7,7));
13 
14 imshow("效果图",A);
15 waitKey(0);
16 return 0;
17 }

调用blur函数。
blur的作用是对输入的图像src进行均值滤波后用dst输出。简单来说就是让图像的值变得平滑。Size(7,7)表示扫描范围是7*7,范围内中心的点的像素值改为区域内所有点的像素值的平均值。

函数原型
C++: void blur(InputArray src, OutputArray dst, Size ksize, Point anchor=Point(-1,-1), int borderType=BORDER_DEFAULT )

参数详解如下:
第一个参数,InputArray类型的src,输入图像,即源图像,填Mat类的对象即可。该函数对通道是独立处理的,且可以处理任意通道数的图片。
第二个参数,OutputArray类型的dst,即目标图像,需要和源图片有一样的尺寸和类型。这里可以用Mat::Clone,以源图片为模板,来初始化得到如假包换的目标图。
第三个参数,Size类型(对Size类型稍后有讲解)的ksize,内核的大小。一般这样写Size( w,h )来表示内核的大小( 其中,w 为像素宽度, h为像素高度)。Size(3,3)就表示3x3的核大小,Size(5,5)就表示5x5的核大小
第四个参数,Point类型的anchor,表示锚点(即被平滑的那个点),注意他有默认值Point(-1,-1)。如果这个点坐标是负值的话,就表示取核的中心为锚点,所以默认值Point(-1,-1)表示这个锚点在核的中心。
第五个参数,int类型的borderType,用于推断图像外部像素的某种边界模式。有默认值BORDER_DEFAULT,我们一般不去管它。

canny边缘检测:

#include "stdafx.h"

using namespace std;
using namespace cv;

int main()
{
Mat frame = imread("1.jpg");
imshow("原图",frame);
Mat gray,edge;
cvtColor(frame, gray, CV_BGR2GRAY);

blur(gray, edge, Size(3, 3));
Canny(edge, edge, 3, 9, 3);

imshow("效果图",edge);
waitKey(0);

return 0;
}

上述程序可以实现提取出图片中的轮廓线。但在没有轮廓的区域也会生成莫名的曲线……
Canny函数的参数:原灰度图像,输出图像(可以是原图像),低阈值,高阈值(一般是低阈值的3倍),Sobel内核大小。
如果一个像素的值大于高阈值,则被认为是边缘像素,如果小于低阈值,则被抛弃。如果该点的值在两者之间则当这个点与高于高阈值的像素点连接时我们才保留,否则删除。

颜色空间转换函数cvtColor()
(一)颜色空间分类总结
资料文章网址:
https://blog.csdn.net/u011574296/article/details/70237027
https://blog.csdn.net/keith_bb/article/details/53470170
简单来说,不同的颜色空间各有利弊,但都不能完全满足人们的需要。对于计算机来说,三个颜色分量之间相关度越小越容易处理。
(二)
例程(假装是)

CommandLineParser命令行解析类:
经过一番搜索……发现对我来说没什么用。其优点主要是减少工作量。
以前的版本没这个类时,如果要运行带参数的.exe,必须在命令行中输入文件路径以及各种参数,并且输入的参数格式要与代码中的if语句判断内容格式一样。如果一不小心输错了就很不方便。而且如果想要更改输入格式的话在主函数文件中要相应更改很多地方。现在有了这个类,只需要改keys里面的内容就可以了,并且运行时可以直接在vs下用F5,不需要cmd命令行带参运行。

#include "stdafx.h"

using namespace std;
using namespace cv;

int main()
{
Mat srclmage = imread("1.jpg");

//显示原图像
namedWindow("原图像");
imshow("原图像", srcImage);

//将图像转换为灰度图
Mat grayImage;
cvtColor(srcImage, grayImage, CV_BGR2GRAY); //将图像转换为灰度图
namedWindow("灰度图");
imshow("灰度图", grayImage);

//将图像转换为HSV
Mat HSVImage;
cvtColor(srcImage, HSVImage, COLOR_BGR2HSV); //将图像转换为HSV图
namedWindow("HSV");
imshow("HSV", HSVImage);

waitKey(0);
return 0;
}


createTrackbar()函数用来创建一个可以调节输入变量值的滑动条,并将改控件依附于指定的窗口上。在使用时需要和一个回调函数配合使用。其原型如下:
CV_EXPORTS int createTrackbar(const string& trackbarname, const string& winname,
int* value, int count,
TrackbarCallback onChange = 0,
void* userdata = 0);
其各个参数含义如下:
. const string& trackname: 滑动条名字
. const string& winname: 想要把该滑动条依附到的窗口名字,在程序中可能该窗口名称由namedWindow()声明。
. int* value: 创建滑动条时,滑动条的初始值
. int count: 滑动条的最大值,即所有滑动条的数据变动都要在0-count之间,滑动条最小值为0
. TrackbarCallback onChange = 0: 这是指的回调函数,每次滑动条数据变化时都对该函数进行回调
. void* userdata = 0: 这个是用户传给回调函数的数据,用来处理滑动条数值变动。如果在创建滑动条时,输入value实参是全局变量,则本参数userdata可使用默认值0.

void remap(InputArray src, OutputArray dst, InputArray map1, InputArray map2,

int interpolation, intborderMode = BORDER_CONSTANT,

const Scalar& borderValue = Scalar())

第一个参数:输入图像,即原图像,需要单通道8位或者浮点类型的图像
第二个参数:输出图像,即目标图像,需和原图形一样的尺寸和类型
第三个参数:它有两种可能表示的对象:(1)表示点(x,y)的第一个映射;(2)表示CV_16SC2,CV_32FC1等
第四个参数:它有两种可能表示的对象:(1)若map1表示点(x,y)时,这个参数不代表任何值;(2)表示CV_16UC1,CV_32FC1类型的Y值
第五个参数:插值方式,有四种插值方式:(1)INTER_NEAREST——最近邻插值
(2)INTER_LINEAR——双线性插值(默认)
(3)INTER_CUBIC——双三样条插值(默认)
(4)INTER_LANCZOS4——lanczos插值(默认)
第六个参数:边界模式,默认BORDER_CONSTANT
第七个参数:边界颜色,默认Scalar()黑色

插值方法
在数字图像处理时,有时会碰到小数像素坐标的取值问题。这是需要依据临近像素的值来对该坐标进行插值。
(一)最近邻插值:必须要计算。在待求像素的四个相邻像素中,将距离待求像素最近的邻像素灰度值赋给待求像素。
(二)双线性内插法:利用待求像素四个邻像素的灰度在两个方向上做线性内插。
对(i,j+v),f(i,j)到f(i,j+1)的灰度变化为线性关系,则有:f(i,j+v)=[f(i,j+1)-f(i,j)]*v+f(i,j);
对(i+1,j+v)则有:f(i+1,j+v)=[f(i+1,j+1)-f(i+1,j)]*v+f(i+1,j);
所以,我们有:
f(i+u,j+v)=(1-u)*(1-v)*f(i,j)+(1-u)*v*f(i,j+1)+u*(1-v)*f(i+1,j)+u*v*f(i+1,j+1);
(三)三次内插法
该方法利用三次多项式S(x)求逼近理论上最佳插值函数sin(x)/x。

line函数:
void line(Mat& img, Point pt1, Point pt2, const Scalar& color, int thickness=1, int lineType=8, int shift=0)
img: 要绘制线段的图像。
pt1: 线段的起点。
pt2: 线段的终点。
color: 线段的颜色,通过一个Scalar对象定义。
thickness: 线条的宽度。
lineType: 线段的类型。可以取值8, 4, 和CV_AA, 分别代表8邻接连接线,4邻接连接线和反锯齿连接线。默认值为8邻接。
shift: 坐标点小数点位数。

invert(A,B):
OpenCV里的矩阵求逆函数。将A求逆,结果保存在B中。

gemm(const CvArr* src1, const CvArr* src2, double alpha, const CvArr* src3, double beta, CvArr* dst, int tABC=0 ):
OpenCV中的矩阵相乘函数。
1.Opencv中的矩阵乘法函数gemm只适应于矩阵维数小的情况,当矩阵阶数是1000以内时,Opencv可以1000ms内完成两个矩阵相乘。
2.OpenBlas适合处理高维矩阵相乘,对于小矩阵有点像杀鸡用牛刀,当矩阵维数为1500*3000时,仍然可以在500ms以内完成两个矩阵相乘。
src1:第一输入数组
src2:第二输入数组
alpha:权重1
src3:第三输入数组 (偏移量) 。
beta:权重2
dst:输出数组
tABC:操作标志……一般不去管它。

alpha*src1T*src2 + beta*src3T
函数 cvGEMM 执行通用矩阵乘法:

dst = alpha*op(src1)*op(src2) + beta*op(src3), 这里 op(X) 表明参与运算的是 X 或者 X的转置。

 

原文地址:https://www.cnblogs.com/Shymuel/p/9297659.html