消息关闭
    暂无新消息!

//---------------------------------【头文件、命名空间包含部分】----------------------------
// 描述:包含程序所使用的头文件和命名空间
//------------------------------------------------------------------------------------------------
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/opencv.hpp"
#include <iostream>
using namespace cv;
using namespace std;


//-----------------------------------【宏定义部分】-------------------------------------------- 
// 描述:定义一些辅助宏 
//------------------------------------------------------------------------------------------------ 
#define WINDOW_NAME1 "【原始图】" //为窗口标题定义的宏 
#define WINDOW_NAME2 "【灰度图】"        //为窗口标题定义的宏 
#define WINDOW_NAME3 "【图像轮廓】"        //为窗口标题定义的宏 


//-----------------------------------【全局变量声明部分】--------------------------------------
// 描述:全局变量的声明
//-----------------------------------------------------------------------------------------------
Mat g_grayImage;        //定义灰度
int g_nThresh = 100;   //初始阀值
RNG g_rng(12345);             //定义一个随机函数对象;RNG( )函数的作用为初始化随机数状态的生成器;
Mat g_cannyMat_output;     //canny边缘检测输出
vector<vector<Point> > g_vContours;   //输出轮廓(点容器)
vector<Vec4i> g_vHierarchy;       //hierarchy,可选的输出向量,包含图像的拓扑信息。它是轮廓数量的表示!!!
Mat src; 

bool ldown = false, lup = false;  //点击行为
Point corner1, corner2;  //开始点---结束点
Rect box;        //选中的矩形区域
Mat imageROI;    //ROI区域

//-----------------------------------【全局变量声明部分】--------------------------------------
// 描述:全局变量的声明
//-----------------------------------------------------------------------------------------------
void on_ThreshChange(int, void* );
void on_MouseHandle(int event, int x, int y, int, void*);



//-----------------------------------【main( )函数】--------------------------------------------
// 描述:控制台应用程序的入口函数,我们的程序从这里开始执行
//-----------------------------------------------------------------------------------------------
int main( int argc, char** argv )
{
// 读入原图像, 返回3通道图像数据
src = imread( "1.jpg", 1 );

// 把原图像转化成灰度图像并进行平滑
cvtColor( src, g_grayImage, COLOR_BGR2GRAY );
blur( g_grayImage, g_grayImage, Size(3,3) );   //均值滤波,3X3内核

// 创建新窗口1【原图】
namedWindow( WINDOW_NAME1, WINDOW_AUTOSIZE );
imshow( WINDOW_NAME1, src );
//创建新窗口2【均值滤波后的图】
namedWindow(WINDOW_NAME2, WINDOW_AUTOSIZE);
imshow(WINDOW_NAME2, g_grayImage);
setMouseCallback(WINDOW_NAME2, on_MouseHandle);

waitKey(0);
        on_ThreshChange(0, 0);
return(0);
}

//------------------------【鼠标定义感兴趣区域】----------------------------------------------

void on_MouseHandle(int event, int x, int y, int, void*)
{
//点击鼠标左键
if (event == EVENT_LBUTTONDOWN)
{
ldown = true;  
corner1.x = x;   //点击点坐标
corner1.y = y;

}

//释放鼠标左键
if (event == EVENT_LBUTTONUP)
{
//这里的if是用来控制选择区域不能过小
if (abs(x - corner1.x) > 20 && abs(y - corner1.y) > 20) //abs()是绝对值函数
{
lup = true;
corner2.x = x;
corner2.y = y;

}
else
{
ldown = false;

}
}

if (ldown == true && lup == false) //逻辑与
{
Point pt;
pt.x = x;
pt.y = y;
Mat local_img = g_grayImage.clone();             //将灰度图g_grayImage复制到local_img
rectangle(local_img, corner1, pt, Scalar(0, 0, 255)); //绘制矩形框
imshow(WINDOW_NAME2, local_img);
}

if (ldown == true && lup == true)    
{
box.width = abs(corner1.x - corner2.x);
box.height = abs(corner1.y - corner2.y);
box.x = min(corner1.x, corner2.x);
box.y = min(corner1.y, corner2.y);
imageROI = g_grayImage(Rect(box.x, box.y, box.width, box.height));

                ldown = false;    //标识符否
lup = false;

}

}

//-----------------------------------【on_ThreshChange( )函数】-------------------------------
// 描述:回调函数
//-----------------------------------------------------------------------------------------------
void on_ThreshChange(int, void* )
{

// 使用Canndy检测边缘
Canny(imageROI, g_cannyMat_output, g_nThresh, g_nThresh * 2, 3);

// 找到轮廓
findContours( g_cannyMat_output, g_vContours, g_vHierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0) );

// 计算矩  这里的for循环来计算每个g_vContours轮廓的矩
vector<Moments> mu(g_vContours.size() );
for(unsigned int i = 0; i < g_vContours.size(); i++ )   //unsigned int 为无符号整型的定义
{ mu[i] = moments( g_vContours[i], false ); }          //false为moments函数中的默认参数

//  计算中心矩
vector<Point2f> mc( g_vContours.size() );
for( unsigned int i = 0; i < g_vContours.size(); i++ )
{ mc[i] = Point2f( static_cast<float>(mu[i].m10/mu[i].m00), static_cast<float>(mu[i].m01/mu[i].m00 )); }

// 绘制轮廓
Mat drawing = Mat::zeros( g_cannyMat_output.size(), CV_8UC3 );
for( unsigned int i = 0; i< g_vContours.size(); i++ )
{
Scalar color = Scalar( g_rng.uniform(0, 255), g_rng.uniform(0,255), g_rng.uniform(0,255) );//随机生成颜色值
drawContours( drawing, g_vContours, i, color, 2, 8, g_vHierarchy, 0, Point() );//绘制外层和内层轮廓
circle( drawing, mc[i], 4, color, -1, 8, 0 );;//绘制圆
}

// 显示到窗口3中
namedWindow( WINDOW_NAME3, WINDOW_AUTOSIZE );
imshow( WINDOW_NAME3, drawing );

// 通过m00计算轮廓面积并且和OpenCV函数比较
printf("\t 输出内容: 面积和轮廓长度\n");
for(unsigned  int i = 0; i< g_vContours.size(); i++ )
{
printf(" >通过m00计算出轮廓[%d]的面积: (M_00) = %.2f \n OpenCV函数计算出的面积=%.2f , 长度: %.2f \n\n", i, mu[i].m00, contourArea(g_vContours[i]), arcLength( g_vContours[i], true ) );
cout << "重心坐标=" << mu[i].m10 << ";" << endl << endl;
Scalar color = Scalar( g_rng.uniform(0, 255), g_rng.uniform(0,255), g_rng.uniform(0,255) );
drawContours( drawing, g_vContours, i, color, 2, 8, g_vHierarchy, 0, Point() );
circle( drawing, mc[i], 4, color, -1, 8, 0 );
}
}



这里想实现的目的是用鼠标在一副图上选择感兴趣区域进行边缘检测和面积及边缘重心坐标的输出,可是一调试选择区域后就闪退,停止调试后,光标停在135行findContours()这里,求大神指教哪里出了问题怎么修改。不胜感激。

3个回答