【OpenCV学习笔记 004】 图像的缩放、Canny边缘检测和图像的二值化_canny二值化-程序员宅基地

技术标签: OpenCV编程笔记  OpenCV  

一、图像的缩放

本篇将介绍使用OpenCV来缩放图片。首先介绍几个关键函数——cvResize和cvCreateImage

1.主要函数介绍

1.1 cvResize

函数功能:图像大小变换

函数原型:

voidcvResize(

  const CvArr* src,

  CvArr* dst,

  intinterpolation=CV_INTER_LINEAR

);

函数说明:

第一个参数表示输入图像。

第二个参数表示输出图像。

第三个参数表示插值方法,可以有以下四种:

CV_INTER_NN - 最近邻插值,

CV_INTER_LINEAR - 双线性插值 (缺省使用)

CV_INTER_AREA - 使用象素关系重采样。当图像缩小时候,该方法可以避免波纹出现。当图像放大时,类似于 CV_INTER_NN 方法..

CV_INTER_CUBIC - 立方插值.

这个函数在功能上与Win32 API中的StretchBlt()函数类似。

1.2 cvCreateImage

函数功能:创建图像

函数原型:

IplImage* cvCreateImage(CvSize size, intdepth,intchannels);

函数说明:

第一个参数表示图像的大小。

第二个参数表示图像的深度,可以为IPL_DEPTH_8U,IPL_DEPTH_16U等等。

第三个参数表示图像的通道数。

2. 示例程序代码

有了这二个函数后,不难写出代码:

//缩放图像文件
#include <iostream>
#include <opencv2/opencv.hpp>

using namespace std;
//隐藏控制台窗口
#pragma comment(linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"")  

int main(){

	const char* psrcImageName = "monster.jpg";	
	const char* pdstImageName = "smallMonster.jpg";
	const char* psrcImageTitle = "大怪兽";	
	const char* pdstImageTitle = "小怪兽";

	double fScale = 0.18;	//缩放倍数
	CvSize czSize;	//目标图像尺寸

	//从文件中读取图像
	IplImage *psrcImage = cvLoadImage(psrcImageName, CV_LOAD_IMAGE_UNCHANGED);
	IplImage *pdstImage = NULL;

	//计算目标图像大小  
	czSize.width = psrcImage->width * fScale;
	czSize.height = psrcImage->height * fScale;

	//创建图像并缩放  
	pdstImage = cvCreateImage(czSize, psrcImage->depth, psrcImage->nChannels);
	cvResize(psrcImage, pdstImage, CV_INTER_AREA);

	//创建窗口  
	cvNamedWindow(psrcImageTitle, CV_WINDOW_AUTOSIZE);
	cvNamedWindow(pdstImageTitle, CV_WINDOW_AUTOSIZE);

	//在指定窗口中显示图像  
	cvShowImage(psrcImageTitle, psrcImage);
	cvShowImage(pdstImageTitle, pdstImage);

	//保存图片  
	cvSaveImage(pdstImageName, pdstImage);
	//等待按键事件  
	cvWaitKey();

	cvDestroyWindow(psrcImageTitle);
	cvDestroyWindow(pdstImageTitle);
	cvReleaseImage(&psrcImage);
	cvReleaseImage(&pdstImage);
	return 0;
		
}
程序运行结果如下:

二、Canny边缘检测

图像的边缘检测的原理是检测出图像中所有灰度值变化较大的点,而且这些点连接起来就构成了若干线条,这些线条就可以称为图像的边缘。
    Canny边缘检测算子是John F. Canny于 1986 年开发出来的一个多级边缘检测算法。Canny 边缘检测的数学原理和算法实现这里就不说了,有兴趣的读者可以查阅专业书籍,本文主要介绍如何在OpenCV中对图像进行Canny 边缘检测,下面就来看看这个函数的原型。

1.主要函数

1.1 cvCanny
函数功能:采用Canny方法对图像进行边缘检测
函数原型:

/* Runs canny edge detector */
CVAPI(void)  cvCanny( const CvArr* image, CvArr* edges, double threshold1,
                      double threshold2, int  aperture_size CV_DEFAULT(3) );
函数说明:
第一个参数表示输入图像,必须为单通道灰度图。
第二个参数表示输出的边缘图像,为单通道黑白图。
第三个参数和第四个参数表示阈值,这二个阈值中当中的小阈值用来控制边缘连接,大的阈值用来控制强边缘的初始分割即如果一个像素的梯度大与上限值,则被认为是边缘像素,如果小于下限阈值,则被抛弃。如果该点的梯度在两者之间则当这个点与高于上限值的像素点连接时我们才保留,否则删除。
第五个参数表示Sobel 算子大小,默认为3即表示一个3*3的矩阵。Sobel 算子与高斯拉普拉斯算子都是常用的边缘算子,详细的数学原理可以查阅专业书籍。
为了更好的使用cvCanny()函数,下面再介绍二个实用的函数,这二个函数对后面的程序实现非常有帮助。
1.2 cvCreateTrackbar
函数功能:创建trackbar并添加到指定窗口
函数原型:

/* create trackbar and display it on top of given window, set callback */
CVAPI(int) cvCreateTrackbar( const char* trackbar_name, const char* window_name,
                             int* value, int count, CvTrackbarCallback on_change CV_DEFAULT(NULL));
函数说明:
第一个参数表示该trackbar的名称。
第二个参数表示窗口名称,该trackbar将显示在这个窗口内。
第三个参数表示创建时滑块的位置。
第四个参数表示滑块位置的最大值,最小值固定为0。
第五个参数表示回调函数。当滑块位置有变化时,系统会调用该回调函数。
注:被创建的trackbar默认显示在指定窗口的顶端,可以通过函数cvGetTrackbarPos()来获取trackbar显示的位置信息,以及通过函数cvSetTrackbarPos()来重新设置trackbar的显示位置。
1.3  CvTrackbarCallback
函数功能:cvCreateTrackbar()函数所使用的回调函数
函数定义:
typedef void (CV_CDECL *CvTrackbarCallback)(int pos)
函数说明:
当trackbar位置被改变的时,系统会调用这个回调函数,并将参数pos设置为表示trackbar位置的数值。

2.示例程序代码

//图像的Canny边缘检测  
#include <opencv2/opencv.hpp>  
using namespace std;
IplImage *g_pSrcImage, *g_pCannyImg;
const char *pstrWindowsCannyTitle = "边缘检测图";
//cvCreateTrackbar的回调函数  
void on_trackbar(int threshold)
{
	//canny边缘检测  
	cvCanny(g_pSrcImage, g_pCannyImg, threshold, threshold * 3, 3);
	cvShowImage(pstrWindowsCannyTitle, g_pCannyImg);
}
int main()
{
	const char *pstrImageName = "girl.jpg";
	const char *pstrWindowsSrcTitle = "原图";
	const char *pstrWindowsToolBar = "Threshold";

	//从文件中载入图像的灰度图CV_LOAD_IMAGE_GRAYSCALE - 灰度图  
	g_pSrcImage = cvLoadImage(pstrImageName, CV_LOAD_IMAGE_GRAYSCALE);
	g_pCannyImg = cvCreateImage(cvGetSize(g_pSrcImage), IPL_DEPTH_8U, 1);

	//创建窗口  
	cvNamedWindow(pstrWindowsSrcTitle, CV_WINDOW_AUTOSIZE);
	cvNamedWindow(pstrWindowsCannyTitle, CV_WINDOW_AUTOSIZE);

	//创建滑动条  
	int nThresholdEdge = 1;
	cvCreateTrackbar(pstrWindowsToolBar, pstrWindowsCannyTitle, &nThresholdEdge, 100, on_trackbar);

	//在指定窗口中显示图像  
	cvShowImage(pstrWindowsSrcTitle, g_pSrcImage);
	on_trackbar(1);

	//等待按键事件  
	cvWaitKey();

	cvDestroyWindow(pstrWindowsSrcTitle);
	cvDestroyWindow(pstrWindowsCannyTitle);
	cvReleaseImage(&g_pSrcImage);
	cvReleaseImage(&g_pCannyImg);
	return 0;
}
程序运行结果:


三、图像的二值化

上面介绍了使用Canny算子对图像进行边缘检测。与边缘检测相比,轮廓检测有时能更好的反映图像的内容。而要对图像进行轮廓检测,则必须要先对图像进行二值化,图像的二值化就是将图像上的像素点的灰度值设置为0或255,这样将使整个图像呈现出明显的黑白效果。在数字图像处理中,二值图像占有非常重要的地位,图像的二值化使图像中数据量大为减少,从而能凸显出目标的轮廓。

1.关键函数介绍

下面就介绍OpenCV中对图像进行二值化的关键函数——cvThreshold()。
函数功能:采用Canny方法对图像进行边缘检测函数原型:

CVAPI(double)  cvThreshold( const CvArr*  src, CvArr*  dst,
                            double  threshold, double  max_value,
                            int threshold_type );
函数说明:
第一个参数表示输入图像,必须为单通道灰度图。
第二个参数表示输出的边缘图像,为单通道黑白图。
第三个参数表示阈值
第四个参数表示最大值。
第五个参数表示运算方法。

/* Threshold types */
enum
{
    CV_THRESH_BINARY      =0,  /* value = value > threshold ? max_value : 0       */
    CV_THRESH_BINARY_INV  =1,  /* value = value > threshold ? 0 : max_value       */
    CV_THRESH_TRUNC       =2,  /* value = value > threshold ? threshold : value   */
    CV_THRESH_TOZERO      =3,  /* value = value > threshold ? value : 0           */
    CV_THRESH_TOZERO_INV  =4,  /* value = value > threshold ? 0 : value           */
    CV_THRESH_MASK        =7,
    CV_THRESH_OTSU        =8  /* use Otsu algorithm to choose the optimal threshold value;
                                 combine the flag with one of the above CV_THRESH_* values */
};
2.示例代码

#include <opencv2/opencv.hpp>  
using namespace std;


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

void on_trackbar(int pos)
{
	// 转为二值图  
	cvThreshold(g_pGrayImage, g_pBinaryImage, pos, 255, CV_THRESH_BINARY);
	// 显示二值图  
	cvShowImage(pstrWindowsBinaryTitle, g_pBinaryImage);
}

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

	// 从文件中加载原图  
	IplImage *pSrcImage = cvLoadImage("Baboon.jpg", CV_LOAD_IMAGE_UNCHANGED);

	// 转为灰度图  
	g_pGrayImage = cvCreateImage(cvGetSize(pSrcImage), IPL_DEPTH_8U, 1);
	cvCvtColor(pSrcImage, g_pGrayImage, CV_BGR2GRAY);

	// 创建二值图  
	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;
}
运行结果如下所示,自己动手调试下阈值大小,看看生成的二值图有什么变化。

OpenCV还有个cvAdaptiveThreshold()函数,这个函数会使用Otsu算法(大律法或最大类间方差法)(注1)来计算出一个全局阈值,然后根据这个阈值进行二值化。当然直接使用cvCanny()函数也可以对图像进行二值化(想到怎么传参数了吗?)。

注1.调用cvThreshold()时传入参数CV_THRESH_OTSU也是使用Otsu算法来自动生成一个阈值。

Reference:

http://blog.csdn.net/morewindows/article/details/8239560

http://blog.csdn.net/morewindows/article/details/8239625

http://blog.csdn.net/morewindows/article/details/8239678


版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/DaveBobo/article/details/51794235

智能推荐

Qt探秘——谈ui文件的用法_.ui文件 s-程序员宅基地

文章浏览阅读802次。相信用过Qt Designer的朋友,对Qt Project中的.ui文件并不陌生。这个文件在Qt Designer中并不能直接修改其源代码,而只能通过Qt Designer的图形工具对其进行操作。对于这一点,我不得不要赞一下设计Qt Designer的人,因为这大大可以避免.ui文件中出现语法错误的概率,同时使得程序员能省下大量的程序界面设计时间进而缩短整个程序项目的开发。 从_.ui文件 s

Ubuntu/Windows下利用“HIDAPI”库函数实现与Hid类USB设备通信_ubuntu向hid设备写数据-程序员宅基地

文章浏览阅读1.7k次,点赞2次,收藏8次。转自https://www.cnblogs.com/ChYQ/p/5383828.html一、背景:   最近在做的一个项目需要使用USB传递数据,对USB理解不是很深,USB的系统驱动编写则更是天方 夜谭,因此将设备配置成HID类设备成为了首选。其最大的好处在于,LINUX/Windows系统中均自带HID 设备驱动,免除了USB系统驱动的困扰,同时HID配置为高速设备与全速设备时,其每笔事务传输的最大 字节大小分别为64bytes、1024bytes,亦符合当前..._ubuntu向hid设备写数据

并查集入门学习(4.7华为实习笔试第一题)_初始化 华为笔试-程序员宅基地

文章浏览阅读504次,点赞5次,收藏7次。并查集学习笔记4.7号做华为实习生笔试,第一题都没完全做出来,用了暴力模拟直接超时,考完后,才知道考察并查集,而且和并查集的经典题目找朋友十分类似,作为一个非科班的,没有系统学习过,只是一直在力扣上刷题,可能刷题少了,没有遇到过并查集的题目(恰巧今天刷每日一题,遇到了并查集),也是第一次听说并查集,所以写下这篇笔记,一方面记录一下学习流程,另一方面提醒自己基础不扎实本文根据胡凡老师的算法笔记进行学习的1.前言首先从字面上进行理解并查集,并就是合并(Union),查就是查找(find),集就是集合(s_初始化 华为笔试

多目标启发式算法(NSGA2, MOEA, MOPSO)python实现_mopso python-程序员宅基地

文章浏览阅读1.1w次,点赞17次,收藏180次。多目标启发式算法python实现1. MODA-多目标差分进化算法基于快速非支配排序算法和拥挤度。算法主程序def MODE(nIter, nChr, nPop, F, Cr, func, lb, rb): """多目标差分进化算法主程序 Params: nIter: 迭代次数 nPop: 种群规模 F: 缩放因子 Cr: 交叉概率 func:优化函数 lb: 自变量下界 _mopso python

Unity运行报错:Fatal error in gc: GetThreadContext failed-程序员宅基地

文章浏览阅读5.7k次。Unity运行报错:Fatal error in gc: GetThreadContext failedunity播放视频流图片原因:运行组件被电脑杀毒软件拦截,导致线程出错解决办法:停止安全防护软件神服~..._fatal error in gc

用 Keras 创建自己的图像标题生成器-程序员宅基地

文章浏览阅读540次。总览了解图像字幕生成器如何使用编码器-解码器工作知道如何使用Keras创建自己的图像标题生成器介绍图像标题生成器是人工智能的热门研究领域,涉及图像理解和该图像的语言描述。生成格式正确的句子...

随便推点

Retrofit3-程序员宅基地

文章浏览阅读1.3k次。apply plugin: 'com.android.application'apply plugin: 'org.greenrobot.greendao'android { compileSdkVersion 26 buildToolsVersion "26.0.2" defaultConfig { applicationId "com.examp_retrofit3

Zephyr RTOS_使用zephyer的单片机多吗?-程序员宅基地

文章浏览阅读1k次。IntroductionThe Zephyr OS is based on a small-footprint kernel designed for use on resource-constrained and embedded systems: from simple embedded environmental sensors and LED wearables to sophisti..._使用zephyer的单片机多吗?

数据库连接错误The server time zone value '�й���׼ʱ��' is unrecognized or represents more than one time zone._创建数据库连接失败:the server time zone value ' й-程序员宅基地

文章浏览阅读1.2k次。在做一个Struct2和MyBatis的项目时,遇到报错信息 The server time zone value '�й���׼ʱ��' is unrecognized or represents more than one time zone.经查询可知为Mybatis中的配置文件连接数据库时时区问题,在文件 mybatis-config.xml中<pro..._创建数据库连接失败:the server time zone value ' й

三色SM认证人脸动态视频制作教程_sm视频-程序员宅基地

文章浏览阅读2.2w次,点赞2次,收藏12次。三色SM认证人脸动态视频制作教程原理软件及视频教程分享_sm视频

.NET Core 3.1 的REST 和gRPC 性能测试-程序员宅基地

文章浏览阅读893次。看到越南小哥 的github 上的Evaluating Performance of REST vs. gRPC , 使用的是.NET Core 3.0 , 今天我把它升级到.NET ..._.net grpc 并发能力

python通过win32api、win32clipboard等包实现微信pc端消息自动发送_win32api.keybd_event(86, 0, win32con.keyeventf_key-程序员宅基地

文章浏览阅读7.4k次,点赞20次,收藏68次。一、先导入要使用的包:import win32apiimport win32conimport win32guiimport timeimport win32clipboard as w安装包可以通过pip进行安装 : pip install win32api ,我使用的是Anaconda,直接import。二、找到微信聊天窗口:def FindWindow(chat..._win32api.keybd_event(86, 0, win32con.keyeventf_keyup, 0)

推荐文章

热门文章

相关标签