(原創) 如何使用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<intint> 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->+ color->+ 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) 
 

posted on 2006-11-21 00:24  真 OO无双  阅读(2776)  评论(1编辑  收藏  举报

导航