2015-05-10 20:17:12 whk100312 阅读数 667
  • 程序员的数学:线性代数

    编程的基础是计算机科学,而计算机科学的基础是数学。因此,学习数学有助于巩固编程的基础,写出更健壮的程序。程序员的数学系列课程主要讲解程序员必备的数学知识,借以培养程序员的数学思维。学习者无需精通编程,也无需精通数学。从概率统计、线性代数、微积分、优化理论、随机过程到当前大热的机器学习,讲师幽默风趣,课件精致美观,深入浅出带你重学数学,时间不可重来,知识可以重学!

    2570 人正在学习 去看看 王文凯
%%%%   5-1-1-2 分段线性变换的源程序:
clear all;
X1=imread('E:\role0\001i.bmp');
figure,
imshow(X1)
f0=0;g0=0;
f1=20;g1=10;
f2=180;g2=230;
f3=255;g3=255;
figure,plot([f0,f1,f2,f3],[g0,g1,g2,g3])
axis tight,xlabel('f'),ylabel('g')
title('intensitytransformation')%绘制变换曲线
r1=(g1-g0)/(f1-f0);
b1=g0-r1*f0;
r2=(g2-g1)/(f2-f1);
b2=g1-r2*f1;
r3=(g3-g2)/(f3-f2);
b3=g2-r3*f2;
[m,n]=size(X1);
X2=double(X1);
for i=1:m
    for j=1:n
        f=X2(i,j);
        g(i,j)=0;
        if(f>=f1)&(f<=f2)
            g(i,j)=r1*f+b2;
        elseif(f>=f2)&(f<=f3)
            g(i,j)=r3*f+b3;
        end
    end
end
figure,imshow(mat2gray(g))

2018-06-18 19:49:58 Lynn_whu 阅读数 1394
  • 程序员的数学:线性代数

    编程的基础是计算机科学,而计算机科学的基础是数学。因此,学习数学有助于巩固编程的基础,写出更健壮的程序。程序员的数学系列课程主要讲解程序员必备的数学知识,借以培养程序员的数学思维。学习者无需精通编程,也无需精通数学。从概率统计、线性代数、微积分、优化理论、随机过程到当前大热的机器学习,讲师幽默风趣,课件精致美观,深入浅出带你重学数学,时间不可重来,知识可以重学!

    2570 人正在学习 去看看 王文凯

C#编写简单数字图像处理程序

数字图像处理的平时成绩和编程作业竟然占50%

那就把最近做的事写个札记吧。

 

先放个最终做成提交的效果看看:

 

1.直方图均衡化

 

2.算子锐化

 

3.空域增强

 

一、要达到的目的和效果

  1.打开,保存图片;

  2.获取图像灰度值,图像坐标;

  3.进行线性变换,直方图均衡化处理;

  4.直方图变换增强,以及各种滤波处理;

  5.图像锐化(Kirsch,Laplace,sobel等算子)。

 

二、编程环境及语言

       C#-WindowsForm-VS2015

三、图标

   

最近发现了一个完全免费的矢量图标网站阿里妈妈iconfont,超级好用。

 

 

 

当然也可以自己动手画一个

四、创建窗体

  1.先建一个C#Windows窗体应用程序,设置好保存路径和项目名称;

  2.打开工具箱,找到menuscript,加到窗体中,依次填写菜单以及子菜单的名称,菜单里将完成主要的图像处理操作;

  3.因为要显示处理前后的图片,所以再添加两个picturebox控件,可以设置停靠模式为stretchImage;再加两个groupbox,每个groupbox里添加label和textbox控件,用来显示图像灰度值及坐标,这样窗体基本搭建完成,还是挺简单的。

五、主要代码

 

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Text;
using System.Windows.Forms;


namespace text1
{
    public partial class ImageEnhancement : Form
    {
        public ImageEnhancement()
        {
            InitializeComponent();
        }
        Bitmap bitmap;
        int iw, ih;       
        //打开文件
        private void 打开ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            pictureBox1.Image = null;//先设置两个picturebox为空
            pictureBox2.Image = null;
            //使用 OpenFileDialog类打开图片
            OpenFileDialog open = new OpenFileDialog();
            open.Filter = "图像文件(*.bmp;*.jpg;*gif;*png;*.tif;*.wmf)|"
                        + "*.bmp;*jpg;*gif;*png;*.tif;*.wmf";
            if (open.ShowDialog() == DialogResult.OK)
            {
                try
                {
                    bitmap = (Bitmap)Image.FromFile(open.FileName);
                }
                catch (Exception exp) { MessageBox.Show(exp.Message); }
                pictureBox1.Refresh();
                pictureBox1.Image = bitmap; 
                label6.Text = "原图";
                iw = bitmap.Width;
              ih = bitmap.Height;



            }
        }
        //保存文件
        private void 保存ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            string str;
            SaveFileDialog saveFileDialog1 = new SaveFileDialog();
            saveFileDialog1.Filter = "图像文件(*.BMP)|*.BMP|All File(*.*)|*.*";
            saveFileDialog1.ShowDialog();
            str = saveFileDialog1.FileName;
            pictureBox2.Image.Save(str);


        }
        //退出
        private void 退出ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Close();
        }
        private void label5_Click(object sender, EventArgs e)
        {
        }
        //读取灰度值及坐标
        private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
        {
            Color pointRGB = bitmap.GetPixel(e.X, e.Y);
            textBox1.Text = pointRGB.R.ToString();
            textBox2.Text = pointRGB.G.ToString();
            textBox3.Text = pointRGB.B.ToString();
            textBox4.Text = e.X.ToString();
            textBox5.Text = e.Y.ToString();
            int a = int.Parse(textBox1.Text);
        }
        //线性变换部分
        private void linearPO_Click(object sender, EventArgs e)
        {
            if (bitmap != null)
            {
                linearPOForm linearForm = new linearPOForm();
                if (linearForm.ShowDialog() == DialogResult.OK)
                {
                    Rectangle rect = new Rectangle(0, 0, bitmap.Width, bitmap.Height);
                    System.Drawing.Imaging.BitmapData bmpData = bitmap.LockBits(rect,
                        System.Drawing.Imaging.ImageLockMode.ReadWrite,
                        bitmap.PixelFormat);
                    IntPtr ptr = bmpData.Scan0;
                    //int bytes = bitmap.Width *;
                }
            }
        }
        private void textBox4_TextChanged(object sender, EventArgs e)
        {
        }
        private void label3_Click(object sender, EventArgs e)
        {
        }
        //对比度扩展
        private void 对比度扩展ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (bitmap != null)
            {
                strechDialog dialog = new strechDialog();


                if (dialog.ShowDialog() == DialogResult.OK)
                {
                    this.Text = " 图像增强 对比度扩展 ";
                    Bitmap bm = new Bitmap(pictureBox1.Image);


                    int x1 = Convert.ToInt32(dialog.getX01);
                    int y1 = Convert.ToInt32(dialog.getY01);
                    int x2 = Convert.ToInt32(dialog.getX02);
                    int y2 = Convert.ToInt32(dialog.getY02);


                    //计算灰度映射表
                    int[] pixMap = pixelsMap(x1, y1, x2, y2);


                    //线性拉伸
                    bm = stretch(bm, pixMap, iw, ih);


                    pictureBox2.Refresh();
                    pictureBox2.Image = bm;
                    label7.Text = "对比度扩展结果";
                }
            }
        }

        //计算灰度映射表
        public int[] pixelsMap(int x1, int y1, int x2, int y2)
        {
            int[] pMap = new int[256];            //映射表
            if (x1 > 0)
            {
                double k1 = y1 / x1;              //第1段斜率k1
                //按第1段斜率k1线性变换
                for (int i = 0; i <= x1; i++)
                    pMap[i] = (int)(k1 * i);
            }
            double k2 = (y2 - y1) / (x2 - x1);    //第2段斜率k2

            //按第2段斜率k2线性变换
            for (int i = x1 + 1; i <= x2; i++)
                if (x2 != x1)
                    pMap[i] = y1 + (int)(k2 * (i - x1));
                else
                    pMap[i] = y1;

            if (x2 < 255)
            {
                double k3 = (255 - y2) / (255 - x2);//第2段斜率k2

                //按第3段斜率k3线性变换
                for (int i = x2 + 1; i < 256; i++)
                    pMap[i] = y2 + (int)(k3 * (i - x2));
            }
            return pMap;
        }

        //对比度扩展函数
        public Bitmap stretch(Bitmap bm, int[] map, int iw, int ih)
        {
            Color c = new Color();
            int r, g, b;
            for (int j = 0; j < ih; j++)
            {
                for (int i = 0; i < iw; i++)
                {
                    c = bm.GetPixel(i, j);
                    r = map[c.R];
                    g = map[c.G];
                    b = map[c.B];
                    if (r >= 255) r = 255;
                    if (r < 0) r = 0;
                    if (g >= 255) g = 255;
                    if (g < 0) g = 0;
                    if (b >= 255) b = 255;
                    if (b < 0) b = 0;
                    bm.SetPixel(i, j, Color.FromArgb(r, g, b));
                }
            }
            return bm;
        }
        private void 直方图均衡化ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (bitmap != null)
            {
                this.Text = " 图像增强 直方图均衡化";
                Bitmap bm = new Bitmap(pictureBox1.Image);
                //获取直方图
                int[] hist = gethist(bm, iw, ih);

                //直方图均匀化
                bm = histequal(bm, hist, iw, ih);

                pictureBox2.Refresh();
                pictureBox2.Image = bm;
                label7.Text = "直方图均衡化结果";
                flag = true;
            }
        }
        bool flag = false;                 //直方图均衡化标志

        //显示直方图
        private void 显示直方图ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (flag)
            {
                Bitmap b1 = new Bitmap(pictureBox1.Image);
                Bitmap b2 = new Bitmap(pictureBox2.Image);

                int[] hist1 = gethist(b1, iw, ih);
                int[] hist2 = gethist(b2, iw, ih);
                drawHist(hist1, hist2);
            }
        }

        //获取直方图
        public int[] gethist(Bitmap bm, int iw, int ih)
        {
            int[] h = new int[256];
            for (int j = 0; j < ih; j++)
            {
                for (int i = 0; i < iw; i++)
                {
                    int grey = (bm.GetPixel(i, j)).R;
                    h[grey]++;
                }
            }
            return h;
        }
        //直方图均衡化
        public Bitmap histequal(Bitmap bm, int[] hist, int iw, int ih)
        {
            Color c = new Color();
            double p = (double)255 / (iw * ih);
            double[] sum = new double[256];
            int[] outg = new int[256];
            int r, g, b;
            sum[0] = hist[0];
            for (int i = 1; i < 256; i++)
                sum[i] = sum[i - 1] + hist[i];



            //灰度变换:i-->outg[i]	
            for (int i = 0; i < 256; i++)
                outg[i] = (int)(p * sum[i]);

            for (int j = 0; j < ih; j++)
            {
                for (int i = 0; i < iw; i++)
                {
                    r = (bm.GetPixel(i, j)).R;
                    g = (bm.GetPixel(i, j)).G;
                    b = (bm.GetPixel(i, j)).B;
                    c = Color.FromArgb(outg[r], outg[g], outg[b]);
                    bm.SetPixel(i, j, c);
                }
            }
            return bm;
        }

        public void drawHist(int[] h1, int[] h2)
        {
            //画原图直方图------------------------------------------
            Graphics g = pictureBox1.CreateGraphics();
            Pen pen1 = new Pen(Color.Blue);
            g.Clear(this.BackColor);

           //找出最大的数,进行标准化.
            int maxn = h1[0];
            for (int i = 1; i < 256; i++)
                if (maxn < h1[i])
                    maxn = h1[i];

            for (int i = 0; i < 256; i++)
                h1[i] = h1[i] * 250 / maxn;

            g.FillRectangle(new SolidBrush(Color.White), 0, 0, 255, 255);

            pen1.Color = Color.Red;
            for (int i = 0; i < 256; i++)
                g.DrawLine(pen1, i, 255, i, 255 - h1[i]);

            g.DrawString("" + maxn, this.Font, new SolidBrush(Color.Blue), 0, 0);
 
            label6.Text = "原图直方图";

            //画均衡化后直方图------------------------------------------
            g = pictureBox2.CreateGraphics();
            pen1 = new Pen(Color.Blue);
            g.Clear(this.BackColor);

            //找出最大的数,进行标准化.
            maxn = h2[0];
            for (int i = 1; i < 256; i++)
                if (maxn < h2[i])
                    maxn = h2[i];

            for (int i = 0; i < 256; i++)
                h2[i] = h2[i] * 250 / maxn;

            g.FillRectangle(new SolidBrush(Color.White), 0, 0, 255, 255);

            pen1.Color = Color.Red;
            for (int i = 0; i < 256; i++)
                g.DrawLine(pen1, i, 255, i, 255 - h2[i]);

            g.DrawString("" + maxn, this.Font, new SolidBrush(Color.Blue), 0, 0);
            label7.Text = "均衡化后直方图";
            flag = false;
        }

        private void 阈值滤波ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (bitmap != null)
            {
                this.Text = "图像增强 阈值滤波";
                Bitmap bm = new Bitmap(pictureBox1.Image);
                //阈值滤波
                bm = threshold(bm, iw, ih);

                pictureBox2.Refresh();
                pictureBox2.Image = bm;
                label7.Text = "阈值滤波结果";
            }
        }

   
        //3×3阈值滤波
        public Bitmap threshold(Bitmap bm, int iw, int ih)
        {
            Bitmap obm = new Bitmap(pictureBox1.Image);


            int avr,          //灰度平均 
                sum,          //灰度和
                num = 0,      //计数器
                nT = 4,       //计数器阈值
                T = 50;       //阈值
            int pij, pkl,     //(i,j),(i+k,j+l)处灰度值
                err;          //误差


            for (int j = 1; j < ih - 1; j++)
            {
                for (int i = 1; i < iw - 1; i++)
                {
                    //取3×3块的9个象素, 求和
                    sum = 0;
                    for (int k = -1; k < 2; k++)
                    {
                        for (int l = -1; l < 2; l++)
                        {
                            if ((k != 0) || (l != 0))
                            {
                                pkl = (bm.GetPixel(i + k, j + l)).R;
                                pij = (bm.GetPixel(i, j)).R;
                                err = Math.Abs(pkl - pij);
                                sum = sum + pkl;
                                if (err > T) num++;
                            }
                        }
                    }
                    avr = (int)(sum / 8.0f);         //平均值
                    if (num > nT)
                        obm.SetPixel(i, j, Color.FromArgb(avr, avr, avr));
                }
            }
            return obm;
        }

        private void 均值滤波ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (bitmap != null)
            {
                this.Text = "数字图像处理";
                Bitmap bm = new Bitmap(pictureBox1.Image);
                bm = average(bm, iw, ih);
                pictureBox2.Refresh();
                pictureBox2.Image = bm;
                label7.Text = "均值滤波结果";
            }
        }
        //均值滤波
        public Bitmap average(Bitmap bm, int iw, int ih)
        {
            Bitmap obm = new Bitmap(pictureBox1.Image);
            for (int j = 1; j < ih - 1; j++)
            {
                for (int i = 1; i < iw - 1; i++)
                {
                    int avr;
                    int avr1;
                    int avr2;
                    int sum = 0;
                    int sum1 = 0;
                    int sum2 = 0;
                    for (int k = -1; k <= 1; k++)
                    {
                        for (int l = -1; l <= 1; l++)
                        {
                            sum = sum + (bm.GetPixel(i + k, j + 1).R);
                            sum1 = sum1 + (bm.GetPixel(i + k, j + 1).G);
                            sum2 = sum2 + (bm.GetPixel(i + k, j + 1).B);
                        }
                    }
                    avr = (int)(sum / 9.0f);
                    avr1 = (int)(sum1 / 9.0f);
                    avr2 = (int)(sum2 / 9.0f);
                    obm.SetPixel(i, j, Color.FromArgb(avr, avr1, avr2));
                }
            }
            return obm;
        }

        private void 中值滤波ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (bitmap != null)
            {
          
                  this.Text = "图像增强 中值滤波";
                    Bitmap bm = new Bitmap(pictureBox1.Image);
                    int num  =3;
                    //中值滤波
                    bm = median(bm, iw, ih, num);

                    pictureBox2.Refresh();
                    pictureBox2.Image = bm;
                    label2.Location = new Point(370, 280);
                    if (num == 1) label7.Text = "1X5窗口滤波结果";
                    else if (num == 2) label7.Text = "5X1窗口滤波结果";
                    else if (num == 3) label7.Text = "5X5窗口滤波结果";
                
            }
        }

        //中值滤波方法
        public Bitmap median(Bitmap bm, int iw, int ih, int n)
        {
            Bitmap obm = new Bitmap(pictureBox1.Image);
            for (int j = 2; j < ih - 2; j++)
            {
                int[] dt;
                int[] dt1;
                int[] dt2;
                for (int i = 2; i < iw - 2; i++)
                {
                    int m = 0, r = 0, r1 = 0, r2 = 0, a = 0, b = 0;
                    if (n == 3)
                    {
                        dt = new int[25];
                        dt1 = new int[25];
                        dt2 = new int[25];
                        //取5×5块的25个象素
                        for (int k = -2; k < 3; k++)
                        {
                            for (int l = -2; l < 3; l++)
                            {
                                //取(i+k,j+l)处的象素,赋于数组dt
                                dt[m] = (bm.GetPixel(i + k, j + l)).R;
                                dt1[a] = (bm.GetPixel(i + k, j + l)).G;
                                dt2[b] = (bm.GetPixel(i + k, j + l)).B;
                                m++;
                                a++;
                                b++;
                            }
                        }
                        //冒泡排序,输出中值
                        r = median_sorter(dt, 25); //中值      
                        r1 = median_sorter(dt1, 25);
                        r2 = median_sorter(dt2, 25);
                    }
                    else if (n == 1)
                    {
                        dt = new int[5];

                        //取1×5窗口5个像素
                        dt[0] = (bm.GetPixel(i, j - 2)).R;
                        dt[1] = (bm.GetPixel(i, j - 1)).R;
                        dt[2] = (bm.GetPixel(i, j)).R;
                        dt[3] = (bm.GetPixel(i, j + 1)).R;
                        dt[4] = (bm.GetPixel(i, j + 2)).R;
                        r = median_sorter(dt, 5);   //中值
                        dt1 = new int[5];


                        //取1×5窗口5个像素
                        dt1[0] = (bm.GetPixel(i, j - 2)).G;
                        dt1[1] = (bm.GetPixel(i, j - 1)).G;
                        dt1[2] = (bm.GetPixel(i, j)).G;
                        dt1[3] = (bm.GetPixel(i, j + 1)).G;
                        dt1[4] = (bm.GetPixel(i, j + 2)).G;
                        r1 = median_sorter(dt1, 5);   //中值   
                        dt2 = new int[5];


                        //取1×5窗口5个像素
                        dt2[0] = (bm.GetPixel(i, j - 2)).B;
                        dt2[1] = (bm.GetPixel(i, j - 1)).B;
                        dt2[2] = (bm.GetPixel(i, j)).B;
                        dt2[3] = (bm.GetPixel(i, j + 1)).B;
                        dt2[4] = (bm.GetPixel(i, j + 2)).B;
                        r2 = median_sorter(dt2, 5);   //中值                           
                    }
                    else if (n == 2)
                    {
                        dt = new int[5];


                        //取5×1窗口5个像素
                        dt[0] = (bm.GetPixel(i - 2, j)).R;
                        dt[1] = (bm.GetPixel(i - 1, j)).R;
                        dt[2] = (bm.GetPixel(i, j)).R;
                        dt[3] = (bm.GetPixel(i + 1, j)).R;
                        dt[4] = (bm.GetPixel(i + 2, j)).R;
                        r = median_sorter(dt, 5);  //中值 dt = new int[5];


                        //取5×1窗口5个像素
                        dt1 = new int[5];
                        dt1[0] = (bm.GetPixel(i - 2, j)).G;
                        dt1[1] = (bm.GetPixel(i - 1, j)).G;
                        dt1[2] = (bm.GetPixel(i, j)).G;
                        dt1[3] = (bm.GetPixel(i + 1, j)).G;
                        dt1[4] = (bm.GetPixel(i + 2, j)).G;
                        r1 = median_sorter(dt1, 5);  //中值       

                        //取5×1窗口5个像素
                        dt2 = new int[5];
                        dt2[0] = (bm.GetPixel(i - 2, j)).B;
                        dt2[1] = (bm.GetPixel(i - 1, j)).B;
                        dt2[2] = (bm.GetPixel(i, j)).B;
                        dt2[3] = (bm.GetPixel(i + 1, j)).B;
                        dt2[4] = (bm.GetPixel(i + 2, j)).B;
                        r2 = median_sorter(dt2, 5);  //中值       

                    }
                    obm.SetPixel(i, j, Color.FromArgb(r, r1, r2));         //输出                  
                }
            }
            return obm;
        }
        //冒泡排序,输出中值
        public int median_sorter(int[] dt, int m)
        {
            int tem;
            for (int k = m - 1; k >= 1; k--)
                for (int l = 1; l <= k; l++)
                    if (dt[l - 1] > dt[l])
                    {
                        tem = dt[l];
                        dt[l] = dt[l - 1];
                        dt[l - 1] = tem;
                    }
            return dt[(int)(m / 2)];
        }
        private void pictureBox1_Click(object sender, EventArgs e)
        {
        }


        private void 图像锐化ToolStripMenuItem_Click(object sender, EventArgs e)
        {
           }


        /* 
         * pix    --待检测图像数组
         * iw, ih --待检测图像宽高
         * num    --算子代号.1:Kirsch算子;2:Laplace算子;3:Prewitt算子;5:Sobel算子
       */
        public Bitmap detect(Bitmap bm, int iw, int ih, int num)
          {

           Bitmap b1 = new Bitmap(pictureBox1.Image);

            Color c = new Color();
            int i, j, r;
            int[,] inr = new int[iw, ih]; //红色分量矩阵
            int[,] ing = new int[iw, ih]; //绿色分量矩阵
            int[,] inb = new int[iw, ih]; //蓝色分量矩阵
            int[,] gray = new int[iw, ih];//灰度图像矩阵	

            //转变为灰度图像矩阵

            for (j = 0; j < ih; j++)
            {
                for (i = 0; i < iw; i++)
                {
                    c = bm.GetPixel(i, j);
                    inr[i, j] = c.R;
                    ing[i, j] = c.G;
                    inb[i, j] = c.B;
                    gray[i, j] = (int)((c.R + c.G + c.B) / 3.0);
                }
            }
            if (num == 1)//Kirsch
            {
                int[,] kir0 = {{ 5, 5, 5},
	                           {-3, 0,-3},
	                           {-3,-3,-3}},//kir0

                       kir1 =  {{-3, 5, 5},
	                            {-3, 0, 5},
	                            {-3,-3,-3}},//kir1

                       kir2 = {{-3,-3, 5},
	                           {-3, 0, 5},
	                           {-3,-3, 5}},//kir2

                       kir3 = {{-3,-3,-3},
	                           {-3, 0, 5},
	                           {-3, 5, 5}},//kir3

                       kir4 = {{-3,-3,-3},
	                           {-3, 0,-3},
	                           { 5, 5, 5}},//kir4

                       kir5 = {{-3,-3,-3},
	                           { 5, 0,-3},
	                           { 5, 5,-3}},//kir5

                       kir6 = {{ 5,-3,-3},
	                           { 5, 0,-3},
	                           { 5,-3,-3}},//kir6

                       kir7 = {{ 5, 5,-3},
	                           { 5, 0,-3},
	                           {-3,-3,-3}};//kir7	
                //边缘检测

                int[,] edge0 = new int[iw, ih];

                int[,] edge1 = new int[iw, ih];

                int[,] edge2 = new int[iw, ih];

                int[,] edge3 = new int[iw, ih];

                int[,] edge4 = new int[iw, ih];

                int[,] edge5 = new int[iw, ih];

                int[,] edge6 = new int[iw, ih];

                int[,] edge7 = new int[iw, ih];

                edge0 = edgeEnhance(gray, kir0, iw, ih);
                edge1 = edgeEnhance(gray, kir1, iw, ih);
                edge2 = edgeEnhance(gray, kir2, iw, ih);
                edge3 = edgeEnhance(gray, kir3, iw, ih);
                edge4 = edgeEnhance(gray, kir4, iw, ih);
                edge5 = edgeEnhance(gray, kir5, iw, ih);
                edge6 = edgeEnhance(gray, kir6, iw, ih);
                edge7 = edgeEnhance(gray, kir7, iw, ih);

                int[] tem = new int[8];
                int max;
                for (j = 0; j < ih; j++)
                {
                    for (i = 0; i < iw; i++)
                    {
                        tem[0] = edge0[i, j];
                        tem[1] = edge1[i, j];
                        tem[2] = edge2[i, j];
                        tem[3] = edge3[i, j];
                        tem[4] = edge4[i, j];
                        tem[5] = edge5[i, j];
                        tem[6] = edge6[i, j];
                        tem[7] = edge7[i, j];
                        max = 0;
                        for (int k = 0; k < 8; k++)
                            if (tem[k] > max) max = tem[k];
                        if (max > 255) max = 255;
                        r = 255 - max;
                        b1.SetPixel(i, j, Color.FromArgb(r, r, r));
                    }
                }
            }
            else if (num == 2)                       //Laplace
            {
                int[,] lap1 = {{ 1, 1, 1},
	                           { 1,-8, 1},
	                           { 1, 1, 1}};

                /*byte[][] lap2 = {{ 0, 1, 0},
                                   { 1,-4, 1},
                                   { 0, 1, 0}}; */

                //边缘增强
               int[,] edge = edgeEnhance(gray, lap1, iw, ih);

                for (j = 0; j < ih; j++)
                {
                    for (i = 0; i < iw; i++)
                    {
                        r = edge[i, j];
                        if (r > 255) r = 255;

                        if (r < 0) r = 0;
                        c = Color.FromArgb(r, r, r);
                        b1.SetPixel(i, j, c);
                    }
                }
            }
            else if (num == 3)//Prewitt
            {
                //Prewitt算子D_x模板
                int[,] pre1 = {{ 1, 0,-1},
	                           { 1, 0,-1},
	                           { 1, 0,-1}};

                //Prewitt算子D_y模板
                int[,] pre2 = {{ 1, 1, 1},
	                           { 0, 0, 0},
	                           {-1,-1,-1}};
                int[,] edge1 = edgeEnhance(gray, pre1, iw, ih);
           
                int[,] edge2 = edgeEnhance(gray, pre2, iw, ih);
                for (j = 0; j < ih; j++)
                {
                    for (i = 0; i < iw; i++)
                    {
                        r = Math.Max(edge1[i, j], edge2[i, j]);
                     
                        if(r > 255) r = 255;
                        c = Color.FromArgb(r, r, r);
                        b1.SetPixel(i, j, c);
                    }
                }
            }

            else if (num == 5)                          //Sobel
            {
                int[,] sob1 = {{ 1, 0,-1},
	                           { 2, 0,-2},
	                           { 1, 0,-1}};
                int[,] sob2 = {{ 1, 2, 1},
	                           { 0, 0, 0},
	                           {-1,-2,-1}},

                int[,] edge1 = edgeEnhance(gray, sob1, iw, ih);
                int[,] edge2 = edgeEnhance(gray, sob2, iw, ih);
                for (j = 0; j < ih; j++)
                {
                    for (i = 0; i < iw; i++)
                    {
                        r = Math.Max(edge1[i, j], edge2[i, j]);
                        if(r > 255) r = 255;
                        c = Color.FromArgb(r, r, r);
                        b1.SetPixel(i, j, c);
                    }
                }
            }
            return b1;
        }
        private void kirsch算子锐化ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (bitmap != null)
            {
                // this.Text = " 图像  -  图像锐化 -  Kirsch算子";
                Bitmap bm = new Bitmap(pictureBox1.Image);
                //1: Kirsch锐化
                bm = detect(bm, iw, ih, 1)
                pictureBox2.Refresh();
                pictureBox2.Image = bm;
                label7.Text = " Kirsch算子 锐化结果";
            }
        }
        public int[,] edgeEnhance(int[,] ing, int[,] tmp, int iw, int ih)
        {
            int[,] ed = new int[iw, ih];
            for (int j = 1; j < ih - 1; j++)
            {
                for (int i = 1; i < iw - 1; i++)
                {
                    ed[i, j] = Math.Abs(tmp[0, 0] * ing[i - 1, j - 1]
                             + tmp[0, 1] * ing[i - 1, j] + tmp[0, 2] * ing[i - 1, j + 1]
                             + tmp[1, 0] * ing[i, j - 1] + tmp[1, 1] * ing[i, j]
                             + tmp[1, 2] * ing[i, j + 1] + tmp[2, 0] * ing[i + 1, j - 1]
                             + tmp[2, 1] * ing[i + 1, j] + tmp[2, 2] * ing[i + 1, j + 1]);
                }
            }
            return ed;
        }
        //Laplace算子
        private void laplace算子锐化ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (bitmap != null)
            {    
                Bitmap bm = new Bitmap(pictureBox1.Image);

                //2: Laplace锐化 
                bm = detect(bm, iw, ih, 2);
                pictureBox2.Refresh();
                pictureBox2.Image = bm;
                label7.Text = "Laplace算子 锐化结果";
            }
        }
  
        //Prewitt算子
        private void prewitt算子锐化ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (bitmap != null)
            {
               
                Bitmap bm = new Bitmap(pictureBox1.Image);
                //3:Prewitt锐化
                bm = detect(bm, iw, ih, 3);
                pictureBox2.Refresh();
                pictureBox2.Image = bm;
                label2.Location = new Point(390, 280);
                label7.Text = " Prewitt算子 锐化结果";
            }
        }


        //Roberts算子
        private void roberts算子锐化ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (bitmap != null)
            {
               Bitmap bm = new Bitmap(pictureBox1.Image);
                //Robert边缘检测 
                bm = robert(bm, iw, ih);
               pictureBox2.Refresh();
                pictureBox2.Image = bm;
                label2.Location = new Point(390, 280);
                label7.Text = "Roberts算子 锐化结果";
            }
        }

        //roberts算法
        public Bitmap robert(Bitmap bm, int iw, int ih)
        {
            int r, r0, r1, r2, r3, g, g0, g1, g2, g3, b, b0, b1, b2, b3;
            Bitmap obm = new Bitmap(pictureBox1.Image);
            int[,] inr = new int[iw, ih];//红色分量矩阵
            int[,] ing = new int[iw, ih];//绿色分量矩阵
            int[,] inb = new int[iw, ih];//蓝色分量矩阵
            int[,] gray = new int[iw, ih];//灰度图像矩阵	             

            for (int j = 1; j < ih - 1; j++)
            {
                for (int i = 1; i < iw - 1; i++)
                {
                    r0 = (bm.GetPixel(i, j)).R;
                    r1 = (bm.GetPixel(i, j + 1)).R;
                    r2 = (bm.GetPixel(i + 1, j)).R;
                    r3 = (bm.GetPixel(i + 1, j + 1)).R;
                  
                    r = (int)Math.Sqrt((r0 - r3) * (r0 - r3) + (r1 - r2) * (r1 - r2));

                    g0 = (bm.GetPixel(i, j)).G;
                    g1 = (bm.GetPixel(i, j + 1)).G;
                    g2 = (bm.GetPixel(i + 1, j)).G;
                    g3 = (bm.GetPixel(i + 1, j + 1)).G;
                    g = (int)Math.Sqrt((g0 - g3) * (g0 - g3) + (g1 - g2) * (g1 - g2));

                    b0 = (bm.GetPixel(i, j)).B;
                    b1 = (bm.GetPixel(i, j + 1)).B;
                    b2 = (bm.GetPixel(i + 1, j)).B;
                    b3 = (bm.GetPixel(i + 1, j + 1)).B;
                    b = (int)Math.Sqrt((b0 - b3) * (b0 - b3)
                      + (b1 - b2) * (b1 - b2));

                    if (r < 0)
                        r = 0;                                       //黑色,边缘点
                    if (r > 255)
                        r = 255;

                    obm.SetPixel(i, j, Color.FromArgb(r, r, r));
                }
            }
            return obm;
        }
        //Sobel算子
        private void sobel算子锐化ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (bitmap != null)
            {
                Bitmap bm = new Bitmap(pictureBox1.Image);
                //5: Sobel锐化
                bm = detect(bm, 256, 256, 5);

                pictureBox2.Refresh();
                pictureBox2.Image = bm;

                label7.Text = " Sobel算子 锐化结果";
            }
        }

        private void 低通滤波ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (bitmap != null)
            {
                Bitmap bm = new Bitmap(pictureBox1.Image);
                int num  ;
                for (num = 1; num < 4; num++)
                {
                    //低通滤波
                    bm = lowpass(bm, iw, ih, num);

                    pictureBox2.Refresh();
                    pictureBox2.Image = bm;

                    if (num == 1) label7.Text = "1*5模板低通滤波结果";
                    else if (num == 2) label7.Text = "5*1模板低通滤波结果";
                    else if (num == 3) label7.Text = "5*5模板低通滤波结果";
                }
           }


       }
        //3×3低通滤波方法
        public Bitmap lowpass(Bitmap bm, int iw, int ih, int n)
        {
            Bitmap obm = new Bitmap(pictureBox1.Image);
            int[,] h;

            //定义扩展输入图像矩阵
            int[,] ex_inpix = exinpix(bm, iw, ih);

            //低通滤波
            for (int j = 1; j < ih + 1; j++)
            {
                for (int i = 1; i < iw + 1; i++)
                {
                    int r = 0, sum = 0;

                    //低通模板		
                    h = low_matrix(n);

                    //求3×3窗口9个像素加权和
                    for (int k = -1; k < 2; k++)
                        for (int l = -1; l < 2; l++)
                            sum = sum + h[k + 1, l + 1] * ex_inpix[i + k, j + l];

                    if (n == 1)
                        r = (int)(sum / 9);       //h1平均值
                    else if (n == 2)
                        r = (int)(sum / 10);      //h2
                    else if (n == 3)
                        r = (int)(sum / 16);      //h3 
                    obm.SetPixel(i - 1, j - 1, Color.FromArgb(r, r, r));    //输出                    
                }
            }
            return obm;
        }
        //定义扩展输入图像矩阵
        public int[,] exinpix(Bitmap bm, int iw, int ih)
        {
            int[,] ex_inpix = new int[iw + 2, ih + 2];
            //获取非边界灰度值
            for (int j = 0; j < ih; j++)
                for (int i = 0; i < iw; i++)
                    ex_inpix[i + 1, j + 1] = (bm.GetPixel(i, j)).R;
            //四角点处理
            ex_inpix[0, 0] = ex_inpix[1, 1];
            ex_inpix[0, ih + 1] = ex_inpix[1, ih];
            ex_inpix[iw + 1, 0] = ex_inpix[iw, 1];
            ex_inpix[iw + 1, ih + 1] = ex_inpix[iw, ih];
            //上下边界处理
            for (int j = 1; j < ih + 1; j++)
            {
                ex_inpix[0, j] = ex_inpix[1, j];      //上边界 
                ex_inpix[iw + 1, j] = ex_inpix[iw, j];//下边界
            }

//左右边界处理
            for (int i = 1; i < iw + 1; i++)
            {
                ex_inpix[i, 0] = ex_inpix[i, 1];      //左边界 
                ex_inpix[i, ih + 1] = ex_inpix[i, ih];//右边界
            }
            return ex_inpix;
        }
        //低通滤波模板
        public int[,] low_matrix(int n)
        {
            int[,] h = new int[3, 3];
            if (n == 1)     //h1
            {
                h[0, 0] = 1; h[0, 1] = 1; h[0, 2] = 1;
                h[1, 0] = 1; h[1, 1] = 1; h[1, 2] = 1;
                h[2, 0] = 1; h[2, 1] = 1; h[2, 2] = 1;
            }
            else if (n == 2)//h2
            {
                h[0, 0] = 1; h[0, 1] = 1; h[0, 2] = 1;
                h[1, 0] = 1; h[1, 1] = 2; h[1, 2] = 1;
                h[2, 0] = 1; h[2, 1] = 1; h[2, 2] = 1;
            }
            else if (n == 3)//h3
            {
                h[0, 0] = 1; h[0, 1] = 2; h[0, 2] = 1;
                h[1, 0] = 2; h[1, 1] = 4; h[1, 2] = 2;
                h[2, 0] = 1; h[2, 1] = 2; h[2, 2] = 1;
            }
            return h;
        }

    }
}

 六、参考书籍

2018-11-15 09:35:55 dyq1995 阅读数 458
  • 程序员的数学:线性代数

    编程的基础是计算机科学,而计算机科学的基础是数学。因此,学习数学有助于巩固编程的基础,写出更健壮的程序。程序员的数学系列课程主要讲解程序员必备的数学知识,借以培养程序员的数学思维。学习者无需精通编程,也无需精通数学。从概率统计、线性代数、微积分、优化理论、随机过程到当前大热的机器学习,讲师幽默风趣,课件精致美观,深入浅出带你重学数学,时间不可重来,知识可以重学!

    2570 人正在学习 去看看 王文凯

下面简单介绍一下MATLAB中的图像处理过程:

1、打开MATLAB主界面后,在编辑器中写入以下代码:

I=imread('G:\MATLAB\bm.bmp');

J=double(I);

J=-J+(256-1);                 %图像反转线性变换

H=uint8(J);

subplot(1,2,1),imshow(I);

subplot(1,2,2),imshow(H);

其中I=imread('G:\MATLAB\bm.bmp');这条语句是读取图片的,需要我们先保存图片在对应的文件夹中。

2、代码运行后的结果如下所示:

至此,图像线性变换的结果已完成,请大家继续关注!!!

2011-11-23 15:31:18 honesty2008 阅读数 8892
  • 程序员的数学:线性代数

    编程的基础是计算机科学,而计算机科学的基础是数学。因此,学习数学有助于巩固编程的基础,写出更健壮的程序。程序员的数学系列课程主要讲解程序员必备的数学知识,借以培养程序员的数学思维。学习者无需精通编程,也无需精通数学。从概率统计、线性代数、微积分、优化理论、随机过程到当前大热的机器学习,讲师幽默风趣,课件精致美观,深入浅出带你重学数学,时间不可重来,知识可以重学!

    2570 人正在学习 去看看 王文凯

实验题目:

根据下图参考数据和图像,编程实现数字图像的对比度拉伸。

实验分析:

根据上图,可得:我们只要把图形中灰度值为28-75的像素点修改灰度值即可以完成本次实验。
可以先找出28,75的纵坐标,根据两点式求出该范围内的直线方程。
如设两点坐标为(x0,y1),(x1,y1),则斜率为(y1-y0)/(x1-x0)。

实验程序: lab1.m

function lab1(addr,x1,y1,x2,y2)
%功能:完成实验一,灰度拉伸处理
% addr 为要处理的图片的文件名,默认为images\sy1.jpg
% x1,y1,x2,y2 为拉伸处理的线段端点坐标,当参数小于5个时
% 这些坐标均采用默认值,可以直接按 F5 运行。
if nargin<1
    addr='images\sy1.jpg';
end
if nargin<5
    x1=28;y1=28;
    x2=75;y2=255;
end
if  x1==x2
    display('x1、x2不能相同,退出程序');
    return ;
end
I=imread(addr);
[r,c,n]=size(I);
k=(y1-y2)/(x1-x2);
b=y1-k*x1;
if n>1
    I2=rgb2gray(I);
else I2=I;
end
I2=double(I2);
for x=1:r
    for y=1:c
        tmp=I2(x,y);
        if tmp>=x1 && tmp<=x2
            I2(x,y)=k*tmp+b;
        end
    end
end
subplot(1,2,1);imshow(I);title('original image ');
subplot(1,2,2);imshow(I2,[]);title('image after modification');



2017-04-13 22:25:40 Hk_john 阅读数 539
  • 程序员的数学:线性代数

    编程的基础是计算机科学,而计算机科学的基础是数学。因此,学习数学有助于巩固编程的基础,写出更健壮的程序。程序员的数学系列课程主要讲解程序员必备的数学知识,借以培养程序员的数学思维。学习者无需精通编程,也无需精通数学。从概率统计、线性代数、微积分、优化理论、随机过程到当前大热的机器学习,讲师幽默风趣,课件精致美观,深入浅出带你重学数学,时间不可重来,知识可以重学!

    2570 人正在学习 去看看 王文凯

透视变换(Perspective Transformation)是将图片投影到一个新的视平面(Viewing Plane),也称作投影映射(Projective Mapping)。通用的变换公式为:


u,v是原始图片左边,对应得到变换后的图片坐标x,y,其中
变换矩阵可以拆成4部分,表示线性变换,比如scaling,shearing和ratotion。用于平移,产生透视变换。所以可以理解成仿射等是透视变换的特殊形式。经过透视变换之后的图片通常不是平行四边形(除非映射视平面和原来平面平行的情况)。

重写之前的变换公式可以得到:


所以,已知变换对应的几个点就可以求取变换公式。反之,特定的变换公式也能新的变换后的图片。简单的看一个正方形到四边形的变换:
变换的4组对应点可以表示成:

根据变换公式得到:


定义几个辅助变量:


都为0时变换平面与原来是平行的,可以得到:


不为0时,得到:


求解出的变换矩阵就可以将一个正方形变换到四边形。反之,四边形变换到正方形也是一样的。于是,我们通过两次变换:四边形变换到正方形+正方形变换到四边形就可以将任意一个四边形变换到另一个四边形。


看一段代码:

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. PerspectiveTransform::PerspectiveTransform(float inA11, float inA21,   
  2.                                            float inA31, float inA12,   
  3.                                            float inA22, float inA32,   
  4.                                            float inA13, float inA23,   
  5.                                            float inA33) :   
  6.   a11(inA11), a12(inA12), a13(inA13), a21(inA21), a22(inA22), a23(inA23),  
  7.   a31(inA31), a32(inA32), a33(inA33) {}  
  8.   
  9. PerspectiveTransform PerspectiveTransform::quadrilateralToQuadrilateral(float x0, float y0, float x1, float y1,  
  10.     float x2, float y2, float x3, float y3, float x0p, float y0p, float x1p, float y1p, float x2p, float y2p,  
  11.     float x3p, float y3p) {  
  12.   PerspectiveTransform qToS = PerspectiveTransform::quadrilateralToSquare(x0, y0, x1, y1, x2, y2, x3, y3);  
  13.   PerspectiveTransform sToQ =  
  14.     PerspectiveTransform::squareToQuadrilateral(x0p, y0p, x1p, y1p, x2p, y2p, x3p, y3p);  
  15.   return sToQ.times(qToS);  
  16. }  
  17.   
  18. PerspectiveTransform PerspectiveTransform::squareToQuadrilateral(float x0, float y0, float x1, float y1, float x2,  
  19.     float y2, float x3, float y3) {  
  20.   float dx3 = x0 - x1 + x2 - x3;  
  21.   float dy3 = y0 - y1 + y2 - y3;  
  22.   if (dx3 == 0.0f && dy3 == 0.0f) {  
  23.     PerspectiveTransform result(PerspectiveTransform(x1 - x0, x2 - x1, x0, y1 - y0, y2 - y1, y0, 0.0f,  
  24.                                      0.0f, 1.0f));  
  25.     return result;  
  26.   } else {  
  27.     float dx1 = x1 - x2;  
  28.     float dx2 = x3 - x2;  
  29.     float dy1 = y1 - y2;  
  30.     float dy2 = y3 - y2;  
  31.     float denominator = dx1 * dy2 - dx2 * dy1;  
  32.     float a13 = (dx3 * dy2 - dx2 * dy3) / denominator;  
  33.     float a23 = (dx1 * dy3 - dx3 * dy1) / denominator;  
  34.     PerspectiveTransform result(PerspectiveTransform(x1 - x0 + a13 * x1, x3 - x0 + a23 * x3, x0, y1 - y0  
  35.                                      + a13 * y1, y3 - y0 + a23 * y3, y0, a13, a23, 1.0f));  
  36.     return result;  
  37.   }  
  38. }  
  39.   
  40. PerspectiveTransform PerspectiveTransform::quadrilateralToSquare(float x0, float y0, float x1, float y1, float x2,  
  41.     float y2, float x3, float y3) {  
  42.   // Here, the adjoint serves as the inverse:  
  43.   return squareToQuadrilateral(x0, y0, x1, y1, x2, y2, x3, y3).buildAdjoint();  
  44. }  
  45.   
  46. PerspectiveTransform PerspectiveTransform::buildAdjoint() {  
  47.   // Adjoint is the transpose of the cofactor matrix:  
  48.   PerspectiveTransform result(PerspectiveTransform(a22 * a33 - a23 * a32, a23 * a31 - a21 * a33, a21 * a32  
  49.                                    - a22 * a31, a13 * a32 - a12 * a33, a11 * a33 - a13 * a31, a12 * a31 - a11 * a32, a12 * a23 - a13 * a22,  
  50.                                    a13 * a21 - a11 * a23, a11 * a22 - a12 * a21));  
  51.   return result;  
  52. }  
  53.   
  54. PerspectiveTransform PerspectiveTransform::times(PerspectiveTransform other) {  
  55.   PerspectiveTransform result(PerspectiveTransform(a11 * other.a11 + a21 * other.a12 + a31 * other.a13,  
  56.                                    a11 * other.a21 + a21 * other.a22 + a31 * other.a23, a11 * other.a31 + a21 * other.a32 + a31  
  57.                                    * other.a33, a12 * other.a11 + a22 * other.a12 + a32 * other.a13, a12 * other.a21 + a22  
  58.                                    * other.a22 + a32 * other.a23, a12 * other.a31 + a22 * other.a32 + a32 * other.a33, a13  
  59.                                    * other.a11 + a23 * other.a12 + a33 * other.a13, a13 * other.a21 + a23 * other.a22 + a33  
  60.                                    * other.a23, a13 * other.a31 + a23 * other.a32 + a33 * other.a33));  
  61.   return result;  
  62. }  
  63.   
  64. void PerspectiveTransform::transformPoints(vector<float> &points) {  
  65.   int max = points.size();  
  66.   for (int i = 0; i < max; i += 2) {  
  67.     float x = points[i];  
  68.     float y = points[i + 1];  
  69.     float denominator = a13 * x + a23 * y + a33;  
  70.     points[i] = (a11 * x + a21 * y + a31) / denominator;  
  71.     points[i + 1] = (a12 * x + a22 * y + a32) / denominator;  
  72.   }  
  73. }  
对一张透视图片变换回正面图的效果:

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. int main(){  
  2.     Mat img=imread("boy.png");  
  3.     int img_height = img.rows;  
  4.     int img_width = img.cols;  
  5.     Mat img_trans = Mat::zeros(img_height,img_width,CV_8UC3);  
  6.     PerspectiveTransform tansform = PerspectiveTransform::quadrilateralToQuadrilateral(  
  7.         0,0,  
  8.         img_width-1,0,  
  9.         0,img_height-1,  
  10.         img_width-1,img_height-1,  
  11.         150,250, // top left  
  12.         771,0, // top right  
  13.         0,1023,// bottom left  
  14.         650,1023  
  15.         );  
  16.     vector<float> ponits;  
  17.     for(int i=0;i<img_height;i++){  
  18.         for(int j=0;j<img_width;j++){  
  19.             ponits.push_back(j);  
  20.             ponits.push_back(i);  
  21.         }  
  22.     }  
  23.     tansform.transformPoints(ponits);  
  24.     for(int i=0;i<img_height;i++){  
  25.         uchar*  t= img_trans.ptr<uchar>(i);  
  26.         for (int j=0;j<img_width;j++){  
  27.             int tmp = i*img_width+j;  
  28.             int x = ponits[tmp*2];  
  29.             int y = ponits[tmp*2+1];  
  30.             if(x<0||x>(img_width-1)||y<0||y>(img_height-1))  
  31.                 continue;  
  32.             uchar* p = img.ptr<uchar>(y);  
  33.             t[j*3] = p[x*3];  
  34.             t[j*3+1] = p[x*3+1];  
  35.             t[j*3+2] = p[x*3+2];  
  36.         }  
  37.     }  
  38.     imwrite("trans.png",img_trans);  
  39.     return 0;  
  40. }  




另外在OpenCV中也实现了基础的透视变换操作,有关函数使用请见下一篇:【OpenCV】透视变换 Perspective Transformation(续)



(转载请注明作者和出处:http://blog.csdn.net/xiaowei_cqu 未经允许请勿用于商业用途)

灰度级插值-MATLAB

阅读数 1055

c++的数学库---eigen

阅读数 1035

没有更多推荐了,返回首页