(原創) 如何使用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
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 dilation
15Bitmap^ dilation(Bitmap^, const MyPointVec%);
16// Get max gray level by kernel
17GrayLevel getMaxByKernel(Bitmap^, const MyPointVec%, const MyPoint%);
18// Get gray level from Color object
19GrayLevel getGrayLevelFromColor(Color^);
20
21int 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
36MyPointVec 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
84Bitmap^ 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
100GrayLevel 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
124GrayLevel getGrayLevelFromColor(Color^ color) {
125 return (color->R + color->G + color->B) /3;
126}
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 dilation
15Bitmap^ dilation(Bitmap^, const MyPointVec%);
16// Get max gray level by kernel
17GrayLevel getMaxByKernel(Bitmap^, const MyPointVec%, const MyPoint%);
18// Get gray level from Color object
19GrayLevel getGrayLevelFromColor(Color^);
20
21int 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
36MyPointVec 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
84Bitmap^ 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
100GrayLevel 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
124GrayLevel 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)