OpenCv学习篇——图像阈值化算法

一.阈值化算法定义

所谓二值化简单一点讲,就是将图像划分成黑和白,通过设定一个标准如果大于这个标准就设为白,如果小于这个标准,就设为黑,而这个标准,就叫做阈值。

 

二.算法原理

1.RGB图像转灰度图像原理:RGB图像是有3个通道,也就是一个3维的矩阵,而灰度图,大家都知道只有一个通道,那么如何将一个3通道的事物转为1通道的事物呢?其实这其中是有一个转换公式的:

Gray = R*0.299 + G*0.587 + B*0.114

2.阈值化原理

三.代码中用到的OpenCv中的库函数详细解答(OpenCv2.49版本)


1>这些头文件包含二值化算法中的库函数

#include ‘’opencv2\highgui\highgui.hpp‘’
      #include ‘’opencv2\core\core.hpp‘’
      #include ‘’opencv2\imgproc\imgproc.hpp‘’
      #include ‘’opencv2/opencv.hpp‘’
     2>程序开头有这样
#include  #pragma comment(linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"")

这句话是为了屏蔽控制台程序,每次运行都会出现一个类似dos似的黑框框为了美观,选择把它给屏蔽了,不屏蔽也不影响功能的使用。

3>加载一幅图像:IplImage *pSrcImage = cvLoadImage("lxy.jpg", CV_LOAD_IMAGE_UNCHANGED);

第一个参数是文件名,存在本工程中的文件夹即可

第二个参数:

cvLoadImage( filename, -1 ); 默认读取图像的原通道数也是本工程选取的参数
cvLoadImage( filename, 0 ); 强制转化读取图像为灰度图
cvLoadImage( filename, 1 ); 读取彩色图
4>转为灰度图像
g_pGrayImage = cvCreateImage(cvGetSize(pSrcImage), IPL_DEPTH_8U, 1);
第一个参数:cvGetSize(pSrcImage)函数得到图像的尺寸,pSrcImage为加载之前原图的指针变量
第二个参数:
图像像素的位深度,值为可以为下面一种:
(
IPL_DEPTH_8U - 8位无符号整数
IPL_DEPTH_8S - 8位符号整数
IPL_DEPTH_16U - 16位无符号整数
IPL_DEPTH_16S - 16位符号整数
IPL_DEPTH_32S - 32位符号整数
IPL_DEPTH_32F - 单精度浮点数
IPL_DEPTH_64F - 双精度浮点数
)
第三个参数为通道数
//channel:通道数
RGB的时候是3
灰度图的时候1 因为要转灰度图所以在工程中这个参数用1
5> 是Opencv里的颜色空间转换函数,可以实现rgb颜色向HSV,HSI等颜色空间的转换,也可以转换为灰度图像。 原型: void cvCvtColor( const CvArr* src, CvArr* dst, int code );
入参:cvCvtColor(pSrcImage, g_pGrayImage, CV_BGR2GRAY);
 src输入的 8-bit,16-bit或 32-bit单倍精度浮点数影像。
    dst输出的8-bit16-bit或 32-bit单倍精度浮点数影像。
code:色彩空间转换的模式,该code来实现不同类型的颜色空间转换。
比如:CV_BGR2GRAY表示转换为灰度图,CV_BGR2HSV将图片从RGB空间转换为HSV空间。
其中当code选用CV_BGR2GRAY时,dst需要是单通道图片(cvcreateimage()最后一个参数是1的时候,就是代表单通道图)。
当code选用CV_BGR2HSV时,对于8位图,需要将rgb值归一化到0-1之间。这样得到HSV图中的H范围才是0-360,S和V的范围是0-1。
6>显示原图 
 cvNamedWindow(pstrWindowsSrcTitle, CV_WINDOW_AUTOSIZE);窗口名字自动适应尺寸
 cvShowImage(pstrWindowsSrcTitle, pSrcImage);//指向原图的指针
7>cvCreateTrackbar(pstrWindowsToolBarName, pstrWindowsBinaryTitle, &nThreshold, 254, on_trackbar);
第一个参数:滑动条的名称
第二个参数:窗口的名称,滑动条不会遮挡图像
第三个参数:当滑动条被拖到时,OpenCV会自动将当前位置所代表的值传给指针指向的整数
第四个参数:最大值
第五个参数:回调函数
解释一下回调函数:
什么是回调函数:
你到一个商店买东西,刚好你要的东西没有货,于是你在店员那里留下了你的电话,过了几天店里有货了,店员就打了你的电话,然后你接到电话后就到店里去取了货。在这个例子里,你的电话号码就叫回调函数,你把电话留给店员就叫登记回调函数,店里后来有货了叫做触发了回调关联的事件,店员给你打电话叫做调用回调函数,你到店里去取货叫做响应回调事件。回答完毕。(摘自知乎)

普通函数与回调函数的区别:

对普通函数的调用:
调用程序发出对普通函数的调用后,程序执行立即转向被调用函数执行,直到被调用函数执行完毕后,再返回调用程序继续执行。从发出调用的程序的角度看,这个过程为“调用-->等待被调用函数执行完毕-->继续执行”

对回调函数调用:
调用程序发出对回调函数的调用后,不等函数执行完毕,立即返回并继续执行。这样,调用程序执和被调用函数同时在执行。当被调函数执行完毕后,被调函数会反过来调用某个事先指定函数,以通知调用程序:函数调用结束。这个过程称为回调(Callback),这正是回调函数名称的由来。

8>转为二值图像。

cvThreshold(g_pGrayImage, g_pBinaryImage, pos, 255, CV_THRESH_BINARY);
//第一个参数表示输入图像,必须为单通道灰度图。
//第二个参数表示输出的边缘图像,为单通道黑白图。
//第三个参数表示阈值
//第四个参数表示最大值。
//第五个参数表示运算方法
 CV_THRESH_BINARY      =0, 

   CV_THRESH_BINARY_INV  =1, 

   CV_THRESH_TRUNC       =2, 

   CV_THRESH_TOZERO      =3, 

   CV_THRESH_TOZERO_INV  =4, 

   CV_THRESH_MASK        =7,

   CV_THRESH_OTSU        =8 

四.程序流程图

五.程序源码

#include ‘’opencv2\highgui\highgui.hpp‘’
#include ‘’opencv2\core\core.hpp‘’
#include ‘’opencv2\imgproc\imgproc.hpp‘’
#include ‘’opencv2/opencv.hpp‘’
using namespace std;

using namespace cv;

#pragma comment(linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"")  //屏蔽控制台程序

IplImage *g_pGrayImage = NULL;
IplImage *g_pBinaryImage = NULL;
const char *pstrWindowsBinaryTitle = "二值图(fzhykx1995)";

void on_trackbar(int pos)
{
// 转为二值图函数
cvThreshold(g_pGrayImage, g_pBinaryImage, pos, 255, CV_THRESH_BINARY);
//第一个参数表示输入图像,必须为单通道灰度图。
//第二个参数表示输出的边缘图像,为单通道黑白图。
//第三个参数表示阈值
//第四个参数表示最大值。
//第五个参数表示运算方法

// 显示二值图 
cvShowImage(pstrWindowsBinaryTitle, g_pBinaryImage);//第一个参数决定确定在哪个存在的窗口中显示图像,第二个参数是IplImage类型指针确定要显示的图像。
}

int main(int argc, char** argv)
{
const char *pstrWindowsSrcTitle = "原图(fzhykx1995)";
const char *pstrWindowsToolBarName = "二值图阈值";

// 从文件中加载原图 
IplImage *pSrcImage = cvLoadImage("lxy.jpg", CV_LOAD_IMAGE_UNCHANGED); //第一个参数是文件名,第二个参数是 

// 转为灰度图 
g_pGrayImage = cvCreateImage(cvGetSize(pSrcImage), IPL_DEPTH_8U, 1);
//cvGetSize()函数得到图像大小
//depth
//图像像素的位深度,值为可以为下面一种:
//IPL_DEPTH_8U - 8位无符号整数
//IPL_DEPTH_8S - 8位符号整数
//IPL_DEPTH_16U - 16位无符号整数
//IPL_DEPTH_16S - 16位符号整数
//IPL_DEPTH_32S - 32位符号整数
//IPL_DEPTH_32F - 单精度浮点数
//IPL_DEPTH_64F - 双精度浮点数
//channel
//IplImage* cvCreateImage(CvSize cvSize(int width, int height), int depth, int channels);
//channel:通道数 RGB的时候是3 灰度图的时候1

cvCvtColor(pSrcImage, g_pGrayImage, CV_BGR2GRAY);//CV_BGR2GRAY是RGB到gray。第一个参数的源图像第二个参数是目标图像

// 创建二值图 
g_pBinaryImage = cvCreateImage(cvGetSize(g_pGrayImage), IPL_DEPTH_8U, 1);

// 显示原图 
 cvNamedWindow(pstrWindowsSrcTitle, CV_WINDOW_AUTOSIZE);//窗口名字自动适应尺寸
cvShowImage(pstrWindowsSrcTitle, pSrcImage);//指向原图
// 创建二值图窗口 
cvNamedWindow(pstrWindowsBinaryTitle, CV_WINDOW_AUTOSIZE);

// 滑动条   
int nThreshold = 0;
cvCreateTrackbar(pstrWindowsToolBarName, pstrWindowsBinaryTitle, &nThreshold, 254, on_trackbar);

on_trackbar(1);

cvWaitKey(0);

cvDestroyWindow(pstrWindowsSrcTitle);
cvDestroyWindow(pstrWindowsBinaryTitle);
cvReleaseImage(&pSrcImage);
cvReleaseImage(&g_pGrayImage);
cvReleaseImage(&g_pBinaryImage);
 return 0;
}

六.测试效果图


猜你喜欢

转载自blog.csdn.net/fzhykx/article/details/79486321