(原創) 如何使用C++/CLI对图片做Grayscale Closing? (.NET) (C++/CLI) (C/C++) (Image Processing)
Closing的算法是:先对图片做Dilation,将结果再做Erosion,其目的在消除影像中的hole。
1
#include "stdafx.h"
2
#include <vector>
3
#include <algorithm>
4
5
using namespace System::Drawing;
6
using namespace System::Drawing::Imaging;
7
8
typedef std::pair<int, int> MyPoint;
9
typedef std::vector<MyPoint> MyPointVec;
10
typedef int GrayLevel;
11
12
// Make kernel by radius
13
MyPointVec makeKernel(const int&);
14
// Process closing
15
Bitmap^ closing(Bitmap^, const MyPointVec%);
16
// Process dilation
17
Bitmap^ dilation(Bitmap^, const MyPointVec%);
18
// Process erosion
19
Bitmap^ erosion(Bitmap^, const MyPointVec%);
20
// Get max gray level by kernel
21
GrayLevel getMaxByKernel(Bitmap^, const MyPointVec%, const MyPoint%);
22
// Get max gray level by kernel
23
GrayLevel getMinByKernel(Bitmap^, const MyPointVec%, const MyPoint%);
24
// Get gray level from Color object
25
GrayLevel getGrayLevelFromColor(Color^);
26
27
int main() {
28
// Read image from lena.jpg
29
Bitmap^ image = gcnew Bitmap("lena.jpg");
30
const int radius = 2;
31
// Make kernel by radius
32
MyPointVec kernel = makeKernel(radius);
33
// New dilated image
34
Bitmap^ newImage = closing(image, kernel);
35
// Save new dilated image to disk
36
newImage->Save("GrayscaleClosing.jpg");
37
38
return 0;
39
}
40
41
// Make kernel by radius
42
MyPointVec makeKernel(const int& radius) {
43
MyPointVec kernel;
44
45
if (radius == 0) {
46
kernel.push_back(std::make_pair(0,0));
47
}
48
else if (radius == 1) {
49
// *
50
// ***
51
// *
52
kernel.push_back(std::make_pair(0,0));
53
kernel.push_back(std::make_pair(1,0));
54
kernel.push_back(std::make_pair(0,1));
55
kernel.push_back(std::make_pair(-1,0));
56
kernel.push_back(std::make_pair(0,-1));
57
}
58
else {
59
kernel.push_back(std::make_pair(-1,2));
60
kernel.push_back(std::make_pair(0,2));
61
kernel.push_back(std::make_pair(1,2));
62
63
kernel.push_back(std::make_pair(-2,1));
64
kernel.push_back(std::make_pair(-1,1));
65
kernel.push_back(std::make_pair(0,1));
66
kernel.push_back(std::make_pair(1,1));
67
kernel.push_back(std::make_pair(2,1));
68
69
kernel.push_back(std::make_pair(-2,0));
70
kernel.push_back(std::make_pair(-1,0));
71
kernel.push_back(std::make_pair(0,0));
72
kernel.push_back(std::make_pair(1,0));
73
kernel.push_back(std::make_pair(2,0));
74
75
kernel.push_back(std::make_pair(-2,-1));
76
kernel.push_back(std::make_pair(-1,-1));
77
kernel.push_back(std::make_pair(0,-1));
78
kernel.push_back(std::make_pair(1,-1));
79
kernel.push_back(std::make_pair(2,-1));
80
81
kernel.push_back(std::make_pair(-1,-2));
82
kernel.push_back(std::make_pair(0,-2));
83
kernel.push_back(std::make_pair(1,-2));
84
}
85
86
return kernel;
87
}
88
89
// Process closing
90
Bitmap^ closing(Bitmap^ image, const MyPointVec% kernel) {
91
Bitmap^ newImage = erosion(dilation(image, kernel), kernel);
92
93
return newImage;
94
}
95
96
// Process dilation
97
Bitmap^ dilation(Bitmap^ image, const MyPointVec% kernel) {
98
// New dilated image
99
Bitmap^ newImage = gcnew Bitmap(image->Width, image->Height);
100
for(int x = 0; x != image->Width; ++x) {
101
for(int y = 0; y != image->Height; ++y) {
102
// Get max gray level by kernel
103
GrayLevel gray = getMaxByKernel(image, kernel, std::make_pair(x,y));
104
// Set max gray level to new dilated image
105
newImage->SetPixel(x, y, Color::FromArgb(gray, gray, gray));
106
}
107
}
108
109
return newImage;
110
}
111
112
// Process erosion
113
Bitmap^ erosion(Bitmap^ image, const MyPointVec% kernel) {
114
// New dilated image
115
Bitmap^ newImage = gcnew Bitmap(image->Width, image->Height);
116
for(int x = 0; x != image->Width; ++x) {
117
for(int y = 0; y != image->Height; ++y) {
118
// Get max gray level by kernel
119
GrayLevel gray = getMinByKernel(image, kernel, std::make_pair(x,y));
120
// Set max gray level to new dilated image
121
newImage->SetPixel(x, y, Color::FromArgb(gray, gray, gray));
122
}
123
}
124
125
return newImage;
126
}
127
128
129
// Get max gray level by kernel
130
GrayLevel getMaxByKernel(Bitmap^ image, const MyPointVec% kernel, const MyPoint% point) {
131
typedef std::vector<GrayLevel> NeighborColor;
132
NeighborColor neighborColor;
133
134
// C++/CLI's new for each syntax
135
for each (MyPoint kpoint in kernel) {
136
int x = point.first + kpoint.first;
137
int y = point.second + kpoint.second;
138
if (x >= 0 && x < image->Width) {
139
if (y >= 0 && y < image->Height) {
140
GrayLevel gray = getGrayLevelFromColor(image->GetPixel(x, y));
141
// push_back new gray level to vector
142
neighborColor.push_back(gray);
143
}
144
}
145
}
146
147
// Use STL max_element() algorithm to get max gray level
148
NeighborColor::iterator maxIter = max_element(neighborColor.begin(), neighborColor.end());
149
150
return *maxIter;
151
}
152
153
// Get min gray level by kernel
154
GrayLevel getMinByKernel(Bitmap^ image, const MyPointVec% kernel, const MyPoint% point) {
155
typedef std::vector<GrayLevel> NeighborColor;
156
NeighborColor neighborColor;
157
158
// C++/CLI's new for each syntax
159
for each (MyPoint kpoint in kernel) {
160
int x = point.first + kpoint.first;
161
int y = point.second + kpoint.second;
162
if (x >= 0 && x < image->Width) {
163
if (y >= 0 && y < image->Height) {
164
GrayLevel gray = getGrayLevelFromColor(image->GetPixel(x, y));
165
// push_back new gray level to vector
166
neighborColor.push_back(gray);
167
}
168
}
169
}
170
171
// Use STL min_element() algorithm to get max gray level
172
NeighborColor::iterator minIter = min_element(neighborColor.begin(), neighborColor.end());
173
174
return *minIter;
175
}
176
177
178
// Get gray level from Color object
179
GrayLevel getGrayLevelFromColor(Color^ color) {
180
return (color->R + color->

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

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

See Also
如何使用C++/CLI对图片做Grayscale Dilation?
如何使用C++/CLI对图片做Grayscale Erosion?
如何使用C++/CLI对图片做Grayscale Opening?