之前学习Opencv自己比较少动手一行一行敲代码,这也可能导致了我的基础知识不牢,而且光靠那几篇的学习不够,杜老师让我暑假先重新学一遍Opencv,然后弄清楚那些参数等等的功能,在七月底还会有一个小测试给我们来完成,那么现在我打算从http://www.cnblogs.com/skyfsm/p/6872648.html这里的教程一步一步自己实现功能,并且在他的基础上自己看下怎么可以优化参数等等,多百度,多学习理论知识。那么接下来这些天我会更新我这几天自己实现的功能代码以及截图说明。
图像灰度化
图像灰度化太重要了,重要得几乎在每个需要图像处理的地方都需要先用它,因为无论阈值化还是特征提取等等都需要用到灰度图,包括我前些日子小学期用树莓派做的基于Opencv和CNN实现的人脸识别门禁系统,emmmm,看下明天有空的话再把过程写上来吧,那个只是一个小项目而已就是了,纯属娱乐。好了,言归正传,现在讲讲灰度化,灰度化在Opencv中就是一串代码啦。
#include "stdafx.h"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <stdlib.h>
#include <stdio.h>
using namespace std;
using namespace cv;
int main()
{
Mat img1_gray;
Mat img1 = imread("1.jpg");
cvtColor(img1, img1_gray, CV_BGR2GRAY);
cvNamedWindow("sourct", CV_WINDOW_AUTOSIZE);//命名一个窗口,句柄名为"source",下面imshow(window_name,img)的第一个参数就是窗口名
cvNamedWindow("gray", CV_WINDOW_AUTOSIZE);
imshow("source", img1);
imshow("gray", img1_gray);
waitKey(0);
return 0;
}
真正起作用的是cv_Color这个函数,转换图像颜色通道的函数,第一个参数是原图像,第二个参数是新图像,第三个参数是转换为什么图像的宏,CV_BGR2GRAY顾名思义就是BGR三通道彩色图像转换为GRAY灰度图像,2的意思,我想谐音"to"吧
对了,还需提一下的是,imshow的后面一定要有waitKey(0)图像才会显示,不然窗口一直是灰色的,没有图片。
图像阈值化
刚才的图像灰度化只是为了现在的图像阈值化操作做的前期准备工作,因为图像阈值化的图像需要灰度图,所以要先将彩色图片转换为灰度图。
嗯~那既然说到了图像阈值化,那就先看看图像阈值化的原理吧,我从http://www.opencv.org.cn/opencvdoc/2.3.2/html/doc/tutorials/imgproc/threshold/threshold.html这里学习到了图像阈值化的基本操作原理,其实就是当图像某个像素点超过设定的阈值的时候对那个像素的颜色进行把它变为最亮或者最暗的操作啦。
接下来的五个模式的原理是从他的博客中复制过来的,用来以后回顾知识的时候比较方便。
阈值化的类型:
-
OpenCV中提供了阈值(threshold)函数: threshold 。
-
这个函数有5种阈值化类型,在接下来的章节中将会具体介绍。
-
为了解释阈值分割的过程,我们来看一个简单有关像素灰度的图片,该图如下。该图中的蓝色水平线代表着具体的一个阈值。
阈值类型1:二进制阈值化
-
该阈值化类型如下式所示:
-
解释:在运用该阈值类型的时候,先要选定一个特定的阈值量,比如:125,这样,新的阈值产生规则可以解释为大于125的像素点的灰度值设定为最大值(如8位灰度值最大为255),灰度值小于125的像素点的灰度值设定为0。
阈值类型2:反二进制阈值化
-
该阈值类型如下式所示:
-
解释:该阈值化与二进制阈值化相似,先选定一个特定的灰度值作为阈值,不过最后的设定值相反。(在8位灰度图中,例如大于阈值的设定为0,而小于该阈值的设定为255)。
阈值类型3:截断阈值化
-
该阈值化类型如下式所示:
-
解释:同样首先需要选定一个阈值,图像中大于该阈值的像素点被设定为该阈值,小于该阈值的保持不变。(例如:阈值选取为125,那小于125的阈值不改变,大于125的灰度值(230)的像素点就设定为该阈值)。
阈值类型4:阈值化为0
-
该阈值类型如下式所示:
-
解释:先选定一个阈值,然后对图像做如下处理:1 像素点的灰度值大于该阈值的不进行任何改变;2 像素点的灰度值小于该阈值的,其灰度值全部变为0。
阈值类型5:反阈值化为0
-
该阈值类型如下式所示:
-
解释:原理类似于0阈值,但是在对图像做处理的时候相反,即:像素点的灰度值小于该阈值的不进行任何改变,而大于该阈值的部分,其灰度值全部变为0。
总而言之,前两种阈值化操作时是对立的,前两者的结果会将图片变为只有255和0两种亮度的图像。而最后两种是会把图像变为只有0和原亮度的图像。第三种比较特殊啦,用这种操作的话,整张图片的亮度不会超过阈值设定的范围,如果超过设定的阈值,那么会将像素的值赋值为设定的阈值。待会实现下代码。
设置图像阈值的函数:
threshold( src_gray, dst, threshold_value, max_BINARY_value,threshold_type )
函数 threshold<> 会接受到5个参数:
- src_gray: 输入的灰度图像的地址。
- dst: 输出图像的地址。
- threshold_value: 进行阈值操作时阈值的大小。
- max_BINARY_value: 设定的最大灰度值(该参数运用在二进制与反二进制阈值操作中)。
- threshold_type: 阈值的类型。从上面提到的5种中选择出的结果。
这是从opencv库函数里面找到的五个模式分别代表的宏定义,可以把第五个参数换为这个名字或者是数字,如果需要动态调整阈值操作的模式的话用数字比较方便。接下来让我们从第一个模式开始看看效果吧。
// opencv_day1.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <stdlib.h>
#include <stdio.h>
using namespace std;
using namespace cv;
int main()
{
Mat img1_gray;
Mat img1 = imread("1.jpg");
cvtColor(img1, img1_gray, CV_BGR2GRAY);
cvNamedWindow("sourct", CV_WINDOW_AUTOSIZE);
cvNamedWindow("gray", CV_WINDOW_AUTOSIZE);
imshow("source", img1);
imshow("gray", img1_gray);
//全局阈值化操作
int th = 100;//设置的阈值
Mat global;//阈值化后的图像
threshold(img1_gray, global, th, 255, CV_THRESH_BINARY);//选择第一个模式
cvNamedWindow("global", CV_WINDOW_AUTOSIZE);
imshow("global",