Opencv学习教程之漫水填充算法实例详解

2025-05-27 0 52

前言

基本思想是自动选中了和种子点相连的区域,接着将该区域替换成指定的颜色,经常用来标记或者分离图像的一部分进行处理或分析。漫水填充也可以用来从输入图像获取掩码区域,掩码会加速处理过程,或者只处理掩码指定的像素点。其中掩膜Mask用于进一步控制那些区域将被填充颜色(比如说当对同一图像进行多次填充时)。

?

1
int floodFill(inputoutputArray,inputoutputMask,seedPoint,Scalar newVal,Rect* rect=0,Scalar loDiff=Scalar(),Scalar upDiff=Scalar(),int flags=4)

*第一个参数,输入/输出1通道或3通道,8位或浮点图像。

*第二个参数,表示操作掩膜,为单通道,8位,长宽都比输入图像大两个像素点的图像。漫水填充不会填充掩膜mask的非零像素区域,mask中与输入图像(x,y)像素点相对应的点的坐标为(x+1,y+1)。

*第三个参数,漫水填充算法的起始点。

*第四个参数,像素点被染色的值,即在重绘区域的新值。

*第五个参数,用于设置floodFill函数将要重绘区域的最小边界矩形区域,默认值0。

*第六个参数,当前观察像素值与其部件邻域像素值或待加入该部件的种子像素之间的亮度或颜色之负差的最大值。

*第七个参数,当前观察像素值与其部件邻域像素值或待加入该部件的种子像素之间的亮度或颜色之正差的最大值。

*第八个参数,操作标志符。

(1)低八位(第0~7位),用于控制算法的连通性,可取4(默认值)或者8。如果设为4,表示填充算法只考虑当前像素水平方向和垂直方向的相邻点。如果设为8,除上述相邻点外,还会包含对角线方向的相邻点。

(2)高八位部分(16~23位),可以为0或者如下两种选项标识符的组合。

*FLOODFILL_FIXED_RANGE:如果设置为这个标识符,就会考虑当前像素与种子像素之间的差,否则就考虑当前像素与其相邻像素的差,也就是说,这个范围是浮动的。

*FLOODFILL_MASK_ONLY:如果设置为这个标识符,函数不会去填充改变原始图像(也就是忽略第三个参数newVal),而是去填充掩膜图像(mask)。

(3)中间八位部分(8~15位),用于指定填充掩膜图像的值,若为0,则掩码会用1来填充。

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146
#include<opencv2/imgproc/imgproc.hpp>

#include<opencv2/highgui/highgui.hpp>

#include<iostream>

using namespace cv;

using namespace std;

//全局变量声明

Mat g_srcImage,g_dstImage,g_grayImage,g_maskImage;

int g_nlowDifference=20,g_nupDifference=20;//负差、正差最大值

bool g_bIsColor=true;//是否为彩色标识符布尔值

bool g_bUseMask=false;//是否显示掩膜窗口的布尔值

int g_nFillMode=1;//漫水填充模式

int g_nConnectivity=4;//表示floodFill函数标识符第八位的连通值

int g_nNewMaskVal=255;//新的重新绘制的像素值

//鼠标消息onMouse回调函数

static void onMouse(int event,int x,int y,int ,void*)

{

if(event != CV_EVENT_LBUTTONDOWN)//如果鼠标左键没有按下,便返回

return;

//调用floodFill函数之前的参数准备部分**********

Point seed =Point(x,y);

int lowDifference=g_nFillMode==0?0:g_nlowDifference;//空范围的漫水填充,此值设为0,否则设为全局的g_nlowDifference

int upDifference=g_nFillMode==0?0:g_nupDifference;//空范围的漫水填充,此值设为0,否则设为全局的g_nupDifference

//标识符的0~7位为g_nConnectivity,8~15位为g_nNewMaskVal左移8位的值,16~23位为CV_FLOODFILL_FIXED_RANGE或者0

int flags=g_nConnectivity+(g_nNewMaskVal<<8)+(g_nFillMode==1?CV_FLOODFILL_FIXED_RANGE:0);

//随机生成b、g、r的值

int b=(unsigned)theRNG() &255;//随即返回一个0~255之间的值

int g=(unsigned)theRNG() &255;//随即返回一个0~255之间的值

int r=(unsigned)theRNG() &255;//随即返回一个0~255之间的值

Rect ccomp;//定义重绘区域的最小边界矩形区域

//在重绘区域像素的新值,若是彩色图模式,取Scalar(b,g,r);若是灰度图模式,取Scalar(r*0.299+g*0.587+b*0.114)

Scalar newVal=g_bIsColor?Scalar(b,g,r):Scalar(r*0.299+g*0.587+b*0.114);

Mat dst=g_bIsColor?g_dstImage:g_grayImage;//目标图的赋值

int area;

//正式调用floodFill函数**********************

if(g_bUseMask)

{

threshold(g_maskImage, g_maskImage, 1, 128, CV_THRESH_BINARY);

area=floodFill(dst, g_maskImage, seed,newVal,&ccomp,Scalar(lowDifference,lowDifference,lowDifference),Scalar(upDifference,upDifference,upDifference),flags);

imshow("mask",g_maskImage);

}

else

{

area=floodFill(dst, seed, newVal, &ccomp,Scalar(lowDifference,lowDifference,lowDifference),Scalar(upDifference,upDifference,upDifference),flags);

}

imshow("Renderings",dst);

cout<<area<<"个像素被重绘\\n";

}

//main函数

int main()

{

g_srcImage=imread("/Users/new/Desktop/1.jpg");//载入源图

if(!g_srcImage.data){printf("读取图片srcImage错误~!\\n");return false;}

g_srcImage.copyTo(g_dstImage);//复制源图到目标图

cvtColor(g_srcImage, g_grayImage, COLOR_BGR2GRAY);//转换三通道的image0到灰度图

g_maskImage.create(g_srcImage.rows+2, g_srcImage.cols+2, CV_8UC1);//利用Image0的尺寸来初始化掩膜mask

namedWindow("Renderings",CV_WINDOW_AUTOSIZE);

createTrackbar("Low difference:", "Renderings",&g_nlowDifference , 255,0);

createTrackbar("Up difference:", "Renderings",&g_nupDifference , 255,0);

setMouseCallback("Renderings", onMouse,0);//鼠标回调函数

while(1)//循环轮询按键

{

imshow("Renderings",g_bIsColor?g_dstImage:g_grayImage);//显示效果图

int c=waitKey(0);//获取键盘按键

if((c & 255)==27)//判断ESC是否按下,若按下便退出

{

cout<<"程序退出......\\n";

break;

}

switch((char)c)

{

case '1'://如果键盘‘1'被按下,效果图在灰度图,彩色之间互换

if(g_bIsColor)//若原来为彩色,转换为灰度图,并且将掩膜mask所有元素设置为0

{

cout<<"键盘'1'被按下,切换彩色/灰度模式,当前操作为将【彩色模式】切换为【灰度模式】\\n";

cvtColor(g_srcImage, g_grayImage, COLOR_BGR2GRAY);

g_maskImage=Scalar::all(0);

g_bIsColor=false;

}

else//若原来为灰度图,便将原来的彩色图在此赋值给image,并且将掩膜mask所有元素置0

{

cout<<"键盘‘1'被按下, 切换彩色/灰度模式,当前操作为将【灰度模式】切换为【彩色模式】";

g_srcImage.copyTo(g_dstImage);

g_maskImage=Scalar::all(0);

g_bIsColor=true;

}

break;

case '2'://如果键盘‘2'被按下,显示/隐藏掩膜窗口

if(g_bUseMask)

{

destroyWindow("mask");

g_bUseMask=false;

}

else

{

namedWindow("mask",0);

g_maskImage=Scalar::all(0);

imshow("mask",g_maskImage);

g_bUseMask=true;

}

break;

case '3'://如果键盘'3'被按下,恢复原始图像

cout<<"键盘‘3'被按下,恢复原始图像\\n";

g_srcImage.copyTo(g_dstImage);

cvtColor(g_dstImage, g_grayImage, COLOR_BGR2GRAY);

g_maskImage=Scalar::all(0);

break;

case '4'://如果键盘‘4'被按下,使用空范围的漫水填充

cout<<"键盘‘4'被按下,使用空范围的漫水填充\\n";

g_nFillMode=0;

break;

case '5'://如果键盘‘5'被按下,使用渐变、固定范围的漫水填充

cout<<"键盘'5'被按下,使用渐变、固定范围的漫水填充\\n";

g_nFillMode=1;

break;

case '6'://如果键盘‘6'被按下,使用渐变、浮动范围的漫水填充

cout<<"键盘‘6'被按下,使用渐变、浮动范围的漫水填充\\n";

g_nFillMode=2;

break;

case '7'://如果键盘‘7'被按下,操作标识符的低八位使用4位的连接模式

cout<<"键盘‘7'被按下,操作标识符的低八位使用4位的连接模式\\n";

g_nConnectivity=4;

break;

case '8'://如果键盘‘8'被按下,操作标识符的低八位使用8位的连接模式

cout<<"键盘‘8'被按下,操作标识符的低八位使用8位的连接模式\\n";

g_nConnectivity=8;

break;

}

}

return 0;

}

原始彩色图片:

Opencv学习教程之漫水填充算法实例详解

原始灰度图片:

Opencv学习教程之漫水填充算法实例详解

灰度模式-固定范围的漫水填充:

Opencv学习教程之漫水填充算法实例详解

彩色模式-固定范围的漫水填充:

Opencv学习教程之漫水填充算法实例详解

彩色模式-浮动范围的漫水填充:

Opencv学习教程之漫水填充算法实例详解

操作记录:

Opencv学习教程之漫水填充算法实例详解

Opencv技巧

(1)theRNG():int b=(unsigned)theRNG() &255; //随即返回一个0~255之间的值

(2)threshold() :阈值函数

(3)Scalar():Scalar定义可存放1—4个数值的数值。

总结

以上就是这文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如有疑问大家可以留言交流,谢谢大家对快网idc的支持。

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。

快网idc优惠网 建站教程 Opencv学习教程之漫水填充算法实例详解 https://www.kuaiidc.com/74286.html

相关文章

发表评论
暂无评论