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. 大話設計模式, 作者:程杰
全站熱搜
留言列表