1+ #include < iostream>
2+ #include < opencv2/core.hpp>
3+ #include < opencv2/highgui.hpp>
4+ #include < opencv2/imgproc.hpp>
5+
6+
7+ /* **************************************************************************************
8+ Function: 区域生长算法
9+ Input: src 待处理原图像 pt 初始生长点 th 生长的阈值条件
10+ Output: 肺实质的所在的区域 实质区是白色,其他区域是黑色
11+ Description: 生长结果区域标记为白色(255),背景色为黑色(0)
12+ Return: NULL
13+ Others: NULL
14+ ***************************************************************************************/
15+ void RegionGrow (cv::Mat& src, cv::Mat& matDst, cv::Point2i pt, int th)
16+ {
17+ cv::Point2i ptGrowing; // 待生长点位置
18+ int nGrowLable = 0 ; // 标记是否生长过
19+ int nSrcValue = 0 ; // 生长起点灰度值
20+ int nCurValue = 0 ; // 当前生长点灰度值
21+ matDst = cv::Mat::zeros (src.size (), CV_8UC1); // 创建一个空白区域,填充为黑色
22+ // 生长方向顺序数据
23+ int DIR[8 ][2 ] = { { -1 , -1 }, { 0 , -1 }, { 1 , -1 }, { 1 , 0 }, { 1 , 1 }, { 0 , 1 }, { -1 , 1 }, { -1 , 0 } };
24+ std::vector<cv::Point2i> vcGrowPt; // 生长点栈
25+ vcGrowPt.push_back (pt); // 将生长点压入栈中
26+ matDst.at <uchar>(pt.y , pt.x ) = 255 ; // 标记生长点
27+ nSrcValue = src.at <uchar>(pt.y , pt.x ); // 记录生长点的灰度值
28+
29+ while (!vcGrowPt.empty ()) // 生长栈不为空则生长
30+ {
31+ pt = vcGrowPt.back (); // 取出一个生长点
32+ vcGrowPt.pop_back ();
33+
34+ // 分别对八个方向上的点进行生长
35+ for (int i = 0 ; i<8 ; ++i)
36+ {
37+ ptGrowing.x = pt.x + DIR[i][0 ];
38+ ptGrowing.y = pt.y + DIR[i][1 ];
39+ // 检查是否是边缘点
40+ if (ptGrowing.x < 0 || ptGrowing.y < 0 || ptGrowing.x >(src.cols - 1 ) || (ptGrowing.y > src.rows - 1 ))
41+ continue ;
42+
43+ nGrowLable = matDst.at <uchar>(ptGrowing.y , ptGrowing.x ); // 当前待生长点的灰度值
44+
45+ if (nGrowLable == 0 ) // 如果标记点还没有被生长
46+ {
47+ nCurValue = src.at <uchar>(ptGrowing.y , ptGrowing.x );
48+ if (abs (nSrcValue - nCurValue) < th) // 在阈值范围内则生长
49+ {
50+ matDst.at <uchar>(ptGrowing.y , ptGrowing.x ) = 255 ; // 标记为白色
51+ vcGrowPt.push_back (ptGrowing); // 将下一个生长点压入栈中
52+ }
53+ }
54+ }
55+ }
56+
57+ }
58+
59+
60+ void on_MouseHandle (int event, int x, int y, int flags, void * param){
61+ cv::Mat& src = *(cv::Mat*) param;
62+ cv::Mat src_gray, dst;
63+ if (src.channels () > 1 )
64+ cv::cvtColor (src, src_gray, CV_RGB2GRAY);
65+ cv::Point2i pt;
66+ switch (event)
67+ {
68+ // 左键按下
69+ case cv::EVENT_LBUTTONDOWN:
70+ {
71+ // x:列 y:行
72+ pt=cv::Point2i (x, y);
73+ std::cout <<" 种子点位置:" << " (x,y)=" << " (" << x << " ," << y << " )" << std::endl;
74+ }
75+ break ;
76+ // 左键放开
77+ char str[16 ];
78+ case cv::EVENT_LBUTTONUP:
79+ {
80+ cv::circle (src, cv::Point2i (x, y),2 , cv::Scalar (0 , 0 , 255 ), -1 ,CV_AA);
81+ sprintf_s (str, " (%d,%d)" , x, y);
82+ // cv::putText(src, str, cv::Point2i(x, y), 3, 1, cv::Scalar(150, 200,0), 2, 8);
83+ cv::namedWindow (" dst" , CV_WINDOW_NORMAL);// 定义一个dst窗口
84+ pt = cv::Point2i (x, y);
85+ RegionGrow (src_gray,dst,pt,40 ); // 区域生长
86+ cv::bitwise_and (src_gray, dst, dst); // 与运算
87+ imshow (" src" , src);
88+ imshow (" dst" , dst);
89+ }
90+ break ;
91+ }
92+
93+
94+ }
95+
96+
97+ int main (){
98+ cv::Mat src = cv::imread (" I:\\ Learning-and-Practice\\ 2019Change\\ Image process algorithm\\ Img\\ lung2.jpeg" );
99+ if (src.empty ()){
100+ return -1 ;
101+ }
102+ cv::namedWindow (" src" , CV_WINDOW_NORMAL);// 定义一个img窗口
103+ cv::setMouseCallback (" src" , on_MouseHandle, (void *)&src);// 调用回调函数
104+ imshow (" src" , src);
105+ cv::waitKey (0 );
106+ }
0 commit comments