今天接着在看canny边缘检测,却又遇到了问题,用的VS2017 Opencv 3.1.0 ,就是opencv 能读取到图片,但是显示灰色的一个窗口,且一闪而过。
下面是我出现问题的代码:
未运行成功的代码:
//#include "stdafx.h" //这个是加载MFC的头文件用的,需要自己编写,不编写的话,注释即可
#include "cv.h" // OpenCV 文件
#include "cvaux.h"
#include "cxcore.h"
#include "opencv2/opencv.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include
#include
using namespace cv;
using namespace std;
//-----------------------------------【main( )函数】--------------------------------------------
// 描述:控制台应用程序的入口函数,我们的程序从这里开始
//-------------------------------------------------------------------------------------------------
int main()
{
//【0】载入原始图
Mat srcImage = imread("1.jpg");
imshow("yuanshitu", srcImage);
Mat dstImage, edge, grayImage; //参数定义
//【1】创建与src同类型和大小的矩阵(dst)
dstImage.create(srcImage.size(), srcImage.type());
cvtColor(srcImage, grayImage, COLOR_BGR2GRAY);
//【3】先用使用 3x3内核来降噪
blur(grayImage, edge, Size(3, 3));
//【4】运行Canny算子
Canny(edge, edge, 3, 9, 3);
//【5】显示效果图
imshow("xiaoguotu", edge);
waitKey(0);
return 0;
}
然后我上网搜了一下图片显示灰色是什么原因,大多数说是因为你图片没有读取到,图片路径不对等等,于是我加入测试代码,看看到底图片有没有读取成功,
测试代码如下:
/************测试图片是否读取成功********************/
/* if (!srcImage.empty())
{
std::cout << "can load picture" << "\n";
return -1;
}*/
/*************************************************/
将该段代码放到 Mat srcImage = imread(“1.jpg”);之后。
然后运行,dos窗口显示读取成功,这就让我很困惑。
但是之后我添加了一句代码,竟然成功了,如下图
解决办法是,我在 “imshow(“yuanshitu”, srcImage);”语句前面加了“namedWindow(“yuanshitu”, 1);”这句代码,就成功了。网上查了这两个函数的作用,如下:
1.namedWindow函数
顾名思义,namedWindow函数,用于创建一个窗口。函数原型是这样的:
void namedWindow(const string& winname,int flags=WINDOW_AUTOSIZE );
第一个参数,const string&型的name,即填被用作窗口的标识符的窗口名称。
第二个参数,int 类型的flags ,窗口的标识,可以填如下的值:
WINDOW_NORMAL设置了这个值,用户便可以改变窗口的大小(没有限制)
WINDOW_AUTOSIZE如果设置了这个值,窗口大小会自动调整以适应所显示的图像,并且不能手动改变窗口大小。
WINDOW_OPENGL 如果设置了这个值的话,窗口创建的时候便会支持OpenGL。
函数剖析:
首先需要注意的是,它有默认值WINDOW_AUTOSIZE,所以,一般情况下,这个函数我们填一个变量就行了。
namedWindow函数的作用是,通过指定的名字,创建一个可以作为图像和进度条的容器窗口。如果具有相同名称的窗口已经存在,则函数不做任何事情。
我们可以调用destroyWindow()或者destroyAllWindows()函数来关闭窗口,并取消之前分配的与窗口相关的所有内存空间。
但话是这样说,其实对于代码量不大的简单小程序来说,我们完全没有必要手动调用上述的destroyWindow()或者destroyAllWindows()函数,因为在退出时,所有的资源和应用程序的窗口会被操作系统会自动关闭。
2.imshow函数
在指定的窗口中显示一幅图像。
void imshow(const string& winname, InputArray mat);
■ 第一个参数,const string&类型的winname,填需要显示的窗口标识名称。
■ 第二个参数,InputArray 类型的mat,填需要显示的图像。
imshow 函数详解:
imshow 函数用于在指定的窗口中显示图像。如果窗口是用CV_WINDOW_AUTOSIZE(默认值)标志创建的,那么显示图像原始大小。否则,将图像进行缩放以适合窗口。而imshow 函数缩放图像,取决于图像的深度:
如果载入的图像是8位无符号类型(8-bit unsigned),就显示图像本来的样子。
如果图像是16位无符号类型(16-bit unsigned)或32位整型(32-bit integer),便用像素值除以256。也就是说,值的范围是[0,255 x 256]映射到[0,255]。
如果图像是32位浮点型(32-bit floating-point),像素值便要乘以255。也就是说,该值的范围是[0,1]映射到[0,255]。
简单的说,就是namedWindow函数就是显示一个窗口,imshow函数显示图片,似乎大小和namedWindow函数显示的窗口一样大。而毛星云的那本书的参考代码却没有namedWindow函数,也不清楚具体情况是怎么样的,继续学习吧,希望到时候自己能理解,大家谁比较清楚,请指教,哈哈哈
最后把成功的代码贴出来:
成功代码:
//#include "stdafx.h" //这个是加载MFC的头文件用的,需要自己编写,不编写的话,注释即可
#include "cv.h" // OpenCV 文件
#include "cvaux.h"
#include "cxcore.h"
#include "opencv2/opencv.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include
#include
using namespace cv;
using namespace std;
//-----------------------------------【main( )函数】--------------------------------------------
// 描述:控制台应用程序的入口函数,我们的程序从这里开始
//-------------------------------------------------------------------------------------------------
int main()
{
//【0】载入原始图
Mat srcImage = imread("1.jpg");
/************测试图片是否读取成功********************/
/* if (!srcImage.empty())
{
std::cout << "can load picture" << "\n";
return -1;
}*/
/*************************************************/
namedWindow("yuanshitu", 1);
imshow("yuanshitu", srcImage);
Mat dstImage, edge, grayImage; //参数定义
//【1】创建与src同类型和大小的矩阵(dst)
dstImage.create(srcImage.size(), srcImage.type());
cvtColor(srcImage, grayImage, COLOR_BGR2GRAY);
//【3】先用使用 3x3内核来降噪
blur(grayImage, edge, Size(3, 3));
//【4】运行Canny算子
Canny(edge, edge, 3, 9, 3);
//【5】显示效果图
imshow("xiaoguotu", edge);
waitKey(0);
return 0;
}
参考:
https://blog.csdn.net/mao_hui_fei/article/details/77478750