(原創) 如何使用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
5using namespace System::Drawing;
6using namespace System::Drawing::Imaging;
7
8typedef std::pair<int, int> MyPoint;
9typedef std::vector<MyPoint> MyPointVec;
10typedef int GrayLevel;
11
12// Make kernel by radius
13MyPointVec makeKernel(const int&);
14// Process opening
15Bitmap^ opening(Bitmap^, const MyPointVec%);
16// Process dilation
17Bitmap^ dilation(Bitmap^, const MyPointVec%);
18// Process erosion
19Bitmap^ erosion(Bitmap^, const MyPointVec%);
20// Get max gray level by kernel
21GrayLevel getMaxByKernel(Bitmap^, const MyPointVec%, const MyPoint%);
22// Get max gray level by kernel
23GrayLevel getMinByKernel(Bitmap^, const MyPointVec%, const MyPoint%);
24// Get gray level from Color object
25GrayLevel getGrayLevelFromColor(Color^);
26
27int 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
42MyPointVec 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
90Bitmap^ opening(Bitmap^ image, const MyPointVec% kernel) {
91 Bitmap^ newImage = dilation(erosion(image, kernel), kernel);
92
93 return newImage;
94}
95
96// Process dilation
97Bitmap^ 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
113Bitmap^ 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
130GrayLevel 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
154GrayLevel 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
179GrayLevel getGrayLevelFromColor(Color^ color) {
180 return (color->R + color->G + color->B) /3;
181}
2#include <vector>
3#include <algorithm>
4
5using namespace System::Drawing;
6using namespace System::Drawing::Imaging;
7
8typedef std::pair<int, int> MyPoint;
9typedef std::vector<MyPoint> MyPointVec;
10typedef int GrayLevel;
11
12// Make kernel by radius
13MyPointVec makeKernel(const int&);
14// Process opening
15Bitmap^ opening(Bitmap^, const MyPointVec%);
16// Process dilation
17Bitmap^ dilation(Bitmap^, const MyPointVec%);
18// Process erosion
19Bitmap^ erosion(Bitmap^, const MyPointVec%);
20// Get max gray level by kernel
21GrayLevel getMaxByKernel(Bitmap^, const MyPointVec%, const MyPoint%);
22// Get max gray level by kernel
23GrayLevel getMinByKernel(Bitmap^, const MyPointVec%, const MyPoint%);
24// Get gray level from Color object
25GrayLevel getGrayLevelFromColor(Color^);
26
27int 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
42MyPointVec 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
90Bitmap^ opening(Bitmap^ image, const MyPointVec% kernel) {
91 Bitmap^ newImage = dilation(erosion(image, kernel), kernel);
92
93 return newImage;
94}
95
96// Process dilation
97Bitmap^ 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
113Bitmap^ 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
130GrayLevel 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
154GrayLevel 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
179GrayLevel 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?