(原創) 如何使用C++/CLI对图片做Grayscale Dilation? (.NET) (C/C++) (C++/CLI) (GDI+) (Image Processing)
这是我第一次用C++/CLI真正写出一个有用的程序,主要是因为想用STL Generic Algorithm,又想用GDI+,只好放弃C#改用C++/CLI啦。
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 dilation
15
Bitmap^ dilation(Bitmap^, const MyPointVec%);
16
// Get max gray level by kernel
17
GrayLevel getMaxByKernel(Bitmap^, const MyPointVec%, const MyPoint%);
18
// Get gray level from Color object
19
GrayLevel getGrayLevelFromColor(Color^);
20
21
int main() {
22
// Read image from lena.jpg
23
Bitmap^ image = gcnew Bitmap("lena.jpg");
24
const int radius = 2;
25
// Make kernel by radius
26
MyPointVec kernel = makeKernel(radius);
27
// New dilated image
28
Bitmap^ newImage = dilation(image, kernel);
29
// Save new dilated image to disk
30
newImage->Save("GrayscaleDilatedLena.jpg");
31
32
return 0;
33
}
34
35
// Make kernel by radius
36
MyPointVec makeKernel(const int& radius) {
37
MyPointVec kernel;
38
39
if (radius == 0) {
40
kernel.push_back(std::make_pair(0,0));
41
}
42
else if (radius == 1) {
43
// *
44
// ***
45
// *
46
kernel.push_back(std::make_pair(0,0));
47
kernel.push_back(std::make_pair(1,0));
48
kernel.push_back(std::make_pair(0,1));
49
kernel.push_back(std::make_pair(-1,0));
50
kernel.push_back(std::make_pair(0,-1));
51
}
52
else {
53
kernel.push_back(std::make_pair(-1,2));
54
kernel.push_back(std::make_pair(0,2));
55
kernel.push_back(std::make_pair(1,2));
56
57
kernel.push_back(std::make_pair(-2,1));
58
kernel.push_back(std::make_pair(-1,1));
59
kernel.push_back(std::make_pair(0,1));
60
kernel.push_back(std::make_pair(1,1));
61
kernel.push_back(std::make_pair(2,1));
62
63
kernel.push_back(std::make_pair(-2,0));
64
kernel.push_back(std::make_pair(-1,0));
65
kernel.push_back(std::make_pair(0,0));
66
kernel.push_back(std::make_pair(1,0));
67
kernel.push_back(std::make_pair(2,0));
68
69
kernel.push_back(std::make_pair(-2,-1));
70
kernel.push_back(std::make_pair(-1,-1));
71
kernel.push_back(std::make_pair(0,-1));
72
kernel.push_back(std::make_pair(1,-1));
73
kernel.push_back(std::make_pair(2,-1));
74
75
kernel.push_back(std::make_pair(-1,-2));
76
kernel.push_back(std::make_pair(0,-2));
77
kernel.push_back(std::make_pair(1,-2));
78
}
79
80
return kernel;
81
}
82
83
// Process dilation
84
Bitmap^ dilation(Bitmap^ image, const MyPointVec% kernel) {
85
// New dilated image
86
Bitmap^ newImage = gcnew Bitmap(image->Width, image->Height);
87
for(int x = 0; x != image->Width; ++x) {
88
for(int y = 0; y != image->Height; ++y) {
89
// Get max gray level by kernel
90
GrayLevel gray = getMaxByKernel(image, kernel, std::make_pair(x,y));
91
// Set max gray level to new dilated image
92
newImage->SetPixel(x, y, Color::FromArgb(gray, gray, gray));
93
}
94
}
95
96
return newImage;
97
}
98
99
// Get max gray level by kernel
100
GrayLevel getMaxByKernel(Bitmap^ image, const MyPointVec% kernel, const MyPoint% point) {
101
typedef std::vector<GrayLevel> NeighborColor;
102
NeighborColor neighborColor;
103
104
// C++/CLI's new for each syntax
105
for each (MyPoint kpoint in kernel) {
106
int x = point.first + kpoint.first;
107
int y = point.second + kpoint.second;
108
if (x >= 0 && x < image->Width) {
109
if (y >= 0 && y < image->Height) {
110
GrayLevel gray = getGrayLevelFromColor(image->GetPixel(x, y));
111
// push_back new gray level to vector
112
neighborColor.push_back(gray);
113
}
114
}
115
}
116
117
// Use STL max_element() algorithm to get max gray level
118
NeighborColor::iterator maxIter = max_element(neighborColor.begin(), neighborColor.end());
119
120
return *maxIter;
121
}
122
123
// Get gray level from Color object
124
GrayLevel getGrayLevelFromColor(Color^ color) {
125
return (color->R + color->G + color->B) /3;
126
}
#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 dilation 15
Bitmap^ dilation(Bitmap^, const MyPointVec%); 16
// Get max gray level by kernel17
GrayLevel getMaxByKernel(Bitmap^, const MyPointVec%, const MyPoint%);18
// Get gray level from Color object19
GrayLevel getGrayLevelFromColor(Color^);20

21
int main() {22
// Read image from lena.jpg23
Bitmap^ image = gcnew Bitmap("lena.jpg");24
const int radius = 2;25
// Make kernel by radius26
MyPointVec kernel = makeKernel(radius);27
// New dilated image28
Bitmap^ newImage = dilation(image, kernel);29
// Save new dilated image to disk30
newImage->Save("GrayscaleDilatedLena.jpg");31

32
return 0;33
}34

35
// Make kernel by radius36
MyPointVec makeKernel(const int& radius) {37
MyPointVec kernel;38

39
if (radius == 0) {40
kernel.push_back(std::make_pair(0,0));41
}42
else if (radius == 1) {43
// *44
// ***45
// *46
kernel.push_back(std::make_pair(0,0));47
kernel.push_back(std::make_pair(1,0));48
kernel.push_back(std::make_pair(0,1));49
kernel.push_back(std::make_pair(-1,0));50
kernel.push_back(std::make_pair(0,-1));51
}52
else {53
kernel.push_back(std::make_pair(-1,2));54
kernel.push_back(std::make_pair(0,2));55
kernel.push_back(std::make_pair(1,2));56

57
kernel.push_back(std::make_pair(-2,1));58
kernel.push_back(std::make_pair(-1,1));59
kernel.push_back(std::make_pair(0,1));60
kernel.push_back(std::make_pair(1,1));61
kernel.push_back(std::make_pair(2,1));62

63
kernel.push_back(std::make_pair(-2,0));64
kernel.push_back(std::make_pair(-1,0));65
kernel.push_back(std::make_pair(0,0));66
kernel.push_back(std::make_pair(1,0));67
kernel.push_back(std::make_pair(2,0));68

69
kernel.push_back(std::make_pair(-2,-1));70
kernel.push_back(std::make_pair(-1,-1));71
kernel.push_back(std::make_pair(0,-1));72
kernel.push_back(std::make_pair(1,-1));73
kernel.push_back(std::make_pair(2,-1));74

75
kernel.push_back(std::make_pair(-1,-2));76
kernel.push_back(std::make_pair(0,-2));77
kernel.push_back(std::make_pair(1,-2));78
}79

80
return kernel;81
}82

83
// Process dilation 84
Bitmap^ dilation(Bitmap^ image, const MyPointVec% kernel) {85
// New dilated image86
Bitmap^ newImage = gcnew Bitmap(image->Width, image->Height);87
for(int x = 0; x != image->Width; ++x) {88
for(int y = 0; y != image->Height; ++y) {89
// Get max gray level by kernel90
GrayLevel gray = getMaxByKernel(image, kernel, std::make_pair(x,y));91
// Set max gray level to new dilated image92
newImage->SetPixel(x, y, Color::FromArgb(gray, gray, gray));93
}94
}95

96
return newImage;97
}98

99
// Get max gray level by kernel100
GrayLevel getMaxByKernel(Bitmap^ image, const MyPointVec% kernel, const MyPoint% point) {101
typedef std::vector<GrayLevel> NeighborColor;102
NeighborColor neighborColor;103

104
// C++/CLI's new for each syntax105
for each (MyPoint kpoint in kernel) {106
int x = point.first + kpoint.first;107
int y = point.second + kpoint.second;108
if (x >= 0 && x < image->Width) {109
if (y >= 0 && y < image->Height) {110
GrayLevel gray = getGrayLevelFromColor(image->GetPixel(x, y));111
// push_back new gray level to vector112
neighborColor.push_back(gray);113
}114
}115
}116

117
// Use STL max_element() algorithm to get max gray level118
NeighborColor::iterator maxIter = max_element(neighborColor.begin(), neighborColor.end());119

120
return *maxIter;121
}122

123
// Get gray level from Color object124
GrayLevel getGrayLevelFromColor(Color^ color) {125
return (color->R + color->G + color->B) /3;126
}原图

执行结果

由于第一次真枪实弹的用C++/CLI,所以很多还不是很懂,如C++/CLI新的Handle ^,似乎不能用const和reference,且C++/CLI也将reference从&改成%,不过这的地方倒是改的很好,ISO C++在Address of和Reference都用&,我刚学时,也觉得很混淆,改了之后清楚多了。105行用到了for each,这是C++/CLI的新语法,总算从VB和C#学到这个漂亮的语法了!!,118行用到了max_element()这个algorithm,这也是我主要要用STL的原因,当然自己写也不难,不过既然Library有提供漂亮的algorithm,为什么不用呢?STL是我爱上C++的最主要原因。
See Also
如何使用C++/CLI对图片做Grayscale Erosion?
如何使用C++/CLI对图片做Grayscale Opening?
如何使用C++/CLI对图片做Grayscale Closing?
(原創) 如何實現Real Time對Binary Image做Dilation? (SOC) (Verilog) (Image Processing) (DE2-70) (TRDB-D5M) (TRDB-LTM)


浙公网安备 33010602011771号