天天看點

C# EMGU 3.4.1學習筆記(十)綜合示例:實作多種重映射

本示例是《OpenCV3程式設計入門》中7.3.4中的綜合示例程式的C# + EMGU 3.4.1版,示範了重映射函數remap的用法,并可以通過按鍵控制四種不同的映射模式。

其中要變換的四種模式如下:

1. 圖像寬高縮小一半,并居中顯示:

映射方法函數h(i,j) = (2 * j - src.cols / 2 + 0.5, 2 * i - src.rows / 2 + 0.5),所有成對的參數(i,j)都必須符合:

src.rows / 4 < i < 3 * src.rows / 4 和 src.cols / 4 < j < 3 * src.cols / 4;

2. 圖像上下翻轉:h(i,j) = (j, src.rows - i );

3. 圖像左右翻轉:h(i,j) = (src.cols - j, i);

4. 同時執行上下和左右翻轉:h(i,j) = (src.cols - j, src.rows - i)。

程式代碼如下:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Emgu.CV;
using Emgu.CV.CvEnum;
using Emgu.CV.Structure;
using Emgu.CV.Util;

namespace Remap_MultipleTypes
{
    public partial class Form1 : Form
    {
        //定義變量
        Mat srcImage = new Mat(), dstImage = new Mat();
        Mat map_x = new Mat(), map_y = new Mat();

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            //載入原始圖
            srcImage = CvInvoke.Imread("IronMan.jpg");
            if (srcImage.IsEmpty)
                MessageBox.Show("讀取圖檔錯誤,請确認目錄下是否有imread函數指定的圖檔存在!");
            //顯示原始圖
            imageBox1.Image = srcImage;

            //建立和原始圖一樣的效果圖,x重映射圖,y重映射圖
            dstImage.Create(srcImage.Rows, srcImage.Cols, srcImage.Depth, srcImage.NumberOfChannels);
            map_x.Create(srcImage.Rows, srcImage.Cols, DepthType.Cv32F, 1);
            map_y.Create(srcImage.Rows, srcImage.Cols, DepthType.Cv32F, 1);
        }

        //按鍵事件處理
        private void Form1_KeyDown(object sender, KeyEventArgs e)
        {
            //調用自定義函數,根據按鍵來更新map_x和map_y的值
            update_map(e.KeyCode);
            //調用Remap()函數進行重映射
            CvInvoke.Remap(srcImage, dstImage, map_x, map_y, Inter.Linear);
            //顯示效果圖
            imageBox2.Image = dstImage;
            //更新label2的顯示内容
            switch (e.KeyCode)
            {
                case Keys.Escape:
                    MessageBox.Show("程式退出中...");
                    Application.Exit();
                    break;
                case Keys.D1:
                    label2.Text = "效果圖:圖像長寬縮小為原來的一半并居中顯示";
                    break;
                case Keys.D2:
                    label2.Text = "效果圖:圖像上下翻轉";
                    break;
                case Keys.D3:
                    label2.Text = "效果圖:圖像左右翻轉";
                    break;
                case Keys.D4:
                    label2.Text = "效果圖:圖像上下翻轉并左右翻轉";
                    break;
            }
        }

        //自定義函數,根據按鍵來更新map_x和map_y的值
        void update_map(Keys key)
        {
            //C#中指針操作需要在unsafe語句塊中進行
            unsafe
            {
                //定義float*類型的指針,指向map_x和map_y的首位址
                float* ptr_to_map_x = (float*)map_x.DataPointer;
                float* ptr_to_map_y = (float*)map_y.DataPointer;
                //定義步進值
                int step = srcImage.Cols;

                //雙層循環,周遊每一個像素點
                for (int i = 0; i < srcImage.Rows; i++)
                {
                    for (int j = 0; j < srcImage.Cols; j++)
                    {
                        switch(key)
                        {
                            //若鍵盤【1】鍵被按下,則執行“圖像長寬縮小為原來的一半并居中顯示”的操作
                            case Keys.D1:
                                if (i > srcImage.Rows * 0.25 && i < srcImage.Rows * 0.75 &&
                                    j > srcImage.Cols * 0.25 && j < srcImage.Cols * 0.75)
                                {
                                    ptr_to_map_x[i * step + j] = (float)(2 * j - srcImage.Cols/2 + 0.5);
                                    ptr_to_map_y[i * step + j] = (float)(2 * i - srcImage.Rows/2 + 0.5);
                                }
                                else
                                {
                                    ptr_to_map_x[i * step + j] = 0;
                                    ptr_to_map_y[i * step + j] = 0;
                                }
                                break;
                            //若鍵盤【2】鍵被按下,則執行“圖像上下翻轉”的操作
                            case Keys.D2:
                                ptr_to_map_x[i * step + j] = j;
                                ptr_to_map_y[i * step + j] = srcImage.Rows - i;
                                break;
                            //若鍵盤【3】鍵被按下,則執行“圖像左右翻轉”的操作
                            case Keys.D3:
                                ptr_to_map_x[i * step + j] = srcImage.Cols - j;
                                ptr_to_map_y[i * step + j] = i;
                                break;
                            //若鍵盤【4】鍵被按下,則執行“圖像上下翻轉并左右翻轉”的操作
                            case Keys.D4:
                                ptr_to_map_x[i * step + j] = srcImage.Cols - j;
                                ptr_to_map_y[i * step + j] = srcImage.Rows - i;
                                break;
                        }
                    }
                }
            }
        }

        //按鍵操作說明
        private void toolStripMenuItem2_Click(object sender, EventArgs e)
        {
            Form form2 = new Form(); //建立新視窗
            form2.Size = new Size(410, 150); //定義視窗尺寸
            form2.Show(); //顯示新視窗

            RichTextBox rtb = new RichTextBox(); //建立RichTexBox
            rtb.Dock = DockStyle.Fill; //定義文本框的dock模式
            //文本框的顯示内容
            rtb.AppendText("鍵盤按鍵【ESC】 - 退出程式\n");
            rtb.AppendText("鍵盤按鍵【1】 - 執行“圖像長寬縮小為原來的一半并居中顯示”的操作\n");
            rtb.AppendText("鍵盤按鍵【2】 - 執行“圖像上下翻轉”的操作\n");
            rtb.AppendText("鍵盤按鍵【3】 - 執行“圖像左右翻轉”的操作\n");
            rtb.AppendText("鍵盤按鍵【4】 - 執行“圖像上下翻轉并左右翻轉”的操作");

            form2.Controls.Add(rtb); //将rtb文本框添加到form2窗體中
        }
    }
}
           

程式運作截圖如下:

C# EMGU 3.4.1學習筆記(十)綜合示例:實作多種重映射

完整的程式資源可到如下連結下載下傳:

https://download.csdn.net/download/flymoon87/10687977