close
下圖(A)、(B)、(C)是一般影像處理常見的處理手法,如何撰寫ImgProc blockset讓影像資料,可以像是串流般一直往下進行,本篇將撰寫一個應用範例:將各個獨立影像模組(module)如同積木般堆疊、依照所需要的順序串接,且不限制積木的個數;過程中還能隨時觀看處理前後的結果,甚至恢復上一步(Undo)。
裝飾模式(Decorator)[1]: 動態地給一個物件加入一些額外的職責,就增加功能來說,裝飾模式比產生子類別更為靈活。
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: }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: }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();
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: }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: }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: }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: }參考資料:
1. 大話設計模式, 作者:程杰
全站熱搜










留言列表
