close

下圖(A)、(B)、(C)是一般影像處理常見的處理手法,如何撰寫ImgProc blockset讓影像資料,可以像是串流般一直往下進行,本篇將撰寫一個應用範例:將各個獨立影像模組(module)如同積木般堆疊、依照所需要的順序串接,且不限制積木的個數;過程中還能隨時觀看處理前後的結果,甚至恢復上一步(Undo)。

image

裝飾模式(Decorator)[1]: 動態地給一個物件加入一些額外的職責,就增加功能來說,裝飾模式比產生子類別更為靈活。

image

image

   1: class ImgProc
   2:     {
   3:         private Mat m_srcImg;
   4:         private Mat m_dstImg;
   5:         private ImageBox m_srcImageBox;
   6:         private ImageBox m_dstImageBox;
   7:         public Mat SourceImage
   8:         {
   9:             get { return m_srcImg; }
  10:             set { m_srcImg = value; }
  11:         }
  12:         public Mat TargetImage
  13:         {
  14:             get { return m_dstImg; }
  15:             set { m_dstImg = value; }
  16:         }
  17:  
  18:         public void LoadImage(string filename)
  19:         {
  20:             m_srcImg = CvInvoke.Imread(filename, LoadImageType.Unchanged);
  21:             m_dstImg = m_srcImg.Clone();
  22:         }
  23:         public virtual void SetSrcImageBox(ImageBox imageBox)
  24:         {
  25:             m_srcImageBox = imageBox;
  26:         }
  27:         public virtual void SetDstImageBox(ImageBox imageBox)
  28:         {
  29:             m_dstImageBox = imageBox;
  30:         }
  31:         
  32:         public virtual void ShowSrcImage()
  33:         {
  34:             m_srcImageBox.Image = m_srcImg;
  35:         }
  36:         public virtual void ShowDstImage()
  37:         {
  38:             m_dstImageBox.Image = m_dstImg;
  39:         }
  40:         public virtual void ImageProc()
  41:         {
  42:  
  43:         }
  44:         public virtual void Undo()
  45:         {
  46:             this.m_dstImg = this.m_srcImg.Clone();
  47:         }
  48:     }

image

   1: // Decorator:
   2:     class ImgProcDecorator : ImgProc
   3:     {
   4:         protected ImgProc m_ip;
   5:         
   6:         // 打扮
   7:         public void Decorate(ImgProc ip)
   8:         {
   9:             this.m_ip = ip;
  10:             this.m_ip.SourceImage = ip.TargetImage.Clone();
  11:             this.ImageProc();
  12:          
  13:         }
  14:  
  15:         public override void  ShowDstImage()
  16:         {
  17:             if (m_ip != null)
  18:                 m_ip.ShowDstImage();
  19:         }
  20:         public override void ShowSrcImage()
  21:         {
  22:             if (m_ip != null)
  23:                 m_ip.ShowSrcImage();
  24:         }
  25:  
  26:      
  27:         public override void ImageProc()
  28:         {
  29:             if (m_ip != null)
  30:                 m_ip.ImageProc();
  31:         }
  32:     }

image

   1: //ConcreteDecorator
   2:    class RGB2Gray : ImgProcDecorator
   3:    {
   4:        public override void ImageProc()
   5:        {
   6:            if (m_ip.SourceImage.NumberOfChannels == 3)
   7:                CvInvoke.CvtColor(m_ip.SourceImage, m_ip.TargetImage, ColorConversion.Rgb2Gray);
   8:            else
   9:                throw new Exception("請確認為彩色照片");
  10:        }
  11:    }
  12:    class Gray2BW : ImgProcDecorator
  13:    {
  14:        byte m_thresh;
  15:        public Gray2BW(byte thresh)
  16:        {
  17:            m_thresh = thresh;
  18:        }
  19:        public override void ImageProc()
  20:        {
  21:            CvInvoke.Threshold(m_ip.SourceImage, m_ip.TargetImage, m_thresh, 255, ThresholdType.Binary);    
  22:        }
  23:    }
  24:    class PyrDown : ImgProcDecorator
  25:    {
  26:        public override void ImageProc()
  27:        {
  28:            CvInvoke.PyrDown(m_ip.SourceImage, m_ip.TargetImage);
  29:        }
  30:    }
  31:    class PyrUp : ImgProcDecorator
  32:    {
  33:        public override void ImageProc()
  34:        {
  35:            CvInvoke.PyrUp(m_ip.SourceImage, m_ip.TargetImage);
  36:        }
  37:    }

客戶端程式

   1: ImgProc ip = new ImgProc();

image

   1: private void 載入ToolStripMenuItem_Click(object sender, EventArgs e)
   2:         {
   3:             using (OpenFileDialog ofd = new OpenFileDialog())
   4:             {
   5:                 if (ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
   6:                 {
   7:                     ip.LoadImage(ofd.FileName);
   8:                     ip.SetSrcImageBox(imageBox1);
   9:                     ip.SetDstImageBox(imageBox2);
  10:                     ip.ShowSrcImage();
  11:                     ip.ShowDstImage();
  12:                 }
  13:             }
  14:         }

RGB->Gray

   1: private void rGBGrayToolStripMenuItem_Click(object sender, EventArgs e)
   2:         {
   3:             RGB2Gray rgb2gray = new RGB2Gray();
   4:             try
   5:             {
   6:                 rgb2gray.Decorate(ip);
   7:             }
   8:             catch (Exception ex)
   9:             {
  10:                 MessageBox.Show(ex.Message.ToString());
  11:             }
  12:             ip.ShowSrcImage();
  13:             ip.ShowDstImage();
  14:         }

image

Gray->BW

   1: private void grayBWToolStripMenuItem_Click(object sender, EventArgs e)
   2: {
   3:     Gray2BW gray2bw = new Gray2BW(100);
   4:     gray2bw.Decorate(ip);
   5:     ip.ShowSrcImage();
   6:     ip.ShowDstImage();
   7: }

image

PyrDown

   1: private void pyrDownToolStripMenuItem_Click(object sender, EventArgs e)
   2: {
   3:     PyrDown prydown = new PyrDown();
   4:     prydown.Decorate(ip);
   5:     ip.ShowSrcImage();
   6:     ip.ShowDstImage();
   7: }

image

PyrUp

   1: private void pyrUpToolStripMenuItem_Click(object sender, EventArgs e)
   2: {
   3:     PyrUp pyrup = new PyrUp();
   4:     pyrup.Decorate(ip);
   5:     ip.ShowSrcImage();
   6:     ip.ShowDstImage();
   7: }

image





參考資料:

1. 大話設計模式, 作者:程杰

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 me1237guy 的頭像
    me1237guy

    天天向上

    me1237guy 發表在 痞客邦 留言(0) 人氣()