(原創) 如何使用C++/CLI对图片做Grayscale Opening? (.NET) (C/C++) (C++/CLI) (GDI+) (Image Processing)
Opening的算法是:先对图片做Erosion,将结果再做Dilation,其目的在消除影像中的小杂点。
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 opening
15
Bitmap^ opening(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 = opening(image, kernel);
35
// Save new dilated image to disk
36
newImage->Save("GrayscaleOpening.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 opening
90
Bitmap^ opening(Bitmap^ image, const MyPointVec% kernel) {
91
Bitmap^ newImage = dilation(erosion(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->G + color->B) /3;
181
}
#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 radius13
MyPointVec makeKernel(const int&);14
// Process opening15
Bitmap^ opening(Bitmap^, const MyPointVec%);16
// Process dilation 17
Bitmap^ dilation(Bitmap^, const MyPointVec%); 18
// Process erosion19
Bitmap^ erosion(Bitmap^, const MyPointVec%); 20
// Get max gray level by kernel21
GrayLevel getMaxByKernel(Bitmap^, const MyPointVec%, const MyPoint%);22
// Get max gray level by kernel23
GrayLevel getMinByKernel(Bitmap^, const MyPointVec%, const MyPoint%);24
// Get gray level from Color object25
GrayLevel getGrayLevelFromColor(Color^);26

27
int main() {28
// Read image from lena.jpg29
Bitmap^ image = gcnew Bitmap("lena.jpg");30
const int radius = 2;31
// Make kernel by radius32
MyPointVec kernel = makeKernel(radius);33
// New dilated image34
Bitmap^ newImage = opening(image, kernel);35
// Save new dilated image to disk36
newImage->Save("GrayscaleOpening.jpg");37

38
return 0;39
}40

41
// Make kernel by radius42
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 opening90
Bitmap^ opening(Bitmap^ image, const MyPointVec% kernel) {91
Bitmap^ newImage = dilation(erosion(image, kernel), kernel);92

93
return newImage;94
}95

96
// Process dilation 97
Bitmap^ dilation(Bitmap^ image, const MyPointVec% kernel) {98
// New dilated image99
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 kernel103
GrayLevel gray = getMaxByKernel(image, kernel, std::make_pair(x,y));104
// Set max gray level to new dilated image105
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 image115
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 kernel119
GrayLevel gray = getMinByKernel(image, kernel, std::make_pair(x,y));120
// Set max gray level to new dilated image121
newImage->SetPixel(x, y, Color::FromArgb(gray, gray, gray));122
}123
}124

125
return newImage;126
}127

128

129
// Get max gray level by kernel130
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 syntax135
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 vector142
neighborColor.push_back(gray);143
}144
}145
}146

147
// Use STL max_element() algorithm to get max gray level148
NeighborColor::iterator maxIter = max_element(neighborColor.begin(), neighborColor.end());149

150
return *maxIter;151
}152

153
// Get min gray level by kernel154
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 syntax159
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 vector166
neighborColor.push_back(gray);167
}168
}169
}170

171
// Use STL min_element() algorithm to get max gray level172
NeighborColor::iterator minIter = min_element(neighborColor.begin(), neighborColor.end());173

174
return *minIter;175
}176

177

178
// Get gray level from Color object179
GrayLevel getGrayLevelFromColor(Color^ color) {180
return (color->R + color->G + color->B) /3;181
}原图
执行结果
See Also
如何使用C++/CLI对图片做Grayscale Dilation?
如何使用C++/CLI对图片做Grayscale Erosion?
如何使用C++/CLI对图片做Grayscale Closing?


浙公网安备 33010602011771号