机器视觉入门之路(四七,神奇的线图像的设计B,c#)

其实前面讲的自动对焦的梯度和与线图像中的梯度和是不一样的(两者梯度也不一样),如果你囫囵吞枣,我就要称你“马虎哥”了。实质上,梯度和携带了方向,他不是角度方向,白(255)-黑(0)=255,是正值,方向是白到黑,相反,为负值,则是黑到白。自动对焦中使用绝对值更能体现清晰度,而线图像中梯度和出现最大值,则是白到黑的边界,如果这个最大值带有负号,则出现了黑到白的边界。

好了,为了区分感兴趣区域(ROI),我们重新设计了两条线(|——)来演示线图像。“|”为startLine,为线图像,“——”rccentreLine,非线图像,其中心为m_rcCentre,这条非线图像,用来操作线图像。这是一个“丁”字型设计,为什么要这样设计?原因有二,一,验证他们说的,梯度方向垂直边缘。其二,线图像被拖动旋转时,另一条画线用来验证正确性。代码如下:(如有不懂,参考感兴趣区域(ROI)代码)(梯度方向,这是角度,Gy=图像【x,y+1】-图像【x,y】,Gx=图像【x+1,y】-图像【x,y】,theta=arctan(Gy/Gx))

  public class RoiBase//为自己的线图像服务
    {
        public mg_line RcCentreLine;//-------非线图像
        public mg_line startLine;//|-------   线图像
        public PointF m_RcCenter;//非线图像中心
        public RoiBase()//构造函数,初始化centreline和startline
        {
            PointF start = new PointF(10, 40);
            PointF end = new PointF(70, 40);
            RcCentreLine = new mg_line(start, end);
            m_RcCenter = new PointF((start.X + end.X) / (float)2, (start.Y + end.Y) / (float)2);

            start = new PointF(10, 10);
            end = new PointF(10, 70);
            startLine = new mg_line(start, end);       
        }
        public int IsPointInRect(PointF point)//判断操作是否在相应区域
        {         

            if (point.X <= m_RcCenter.X + 5 && point.X >= m_RcCenter.X - 5
                   && point.Y >= m_RcCenter.Y - 5 && point.Y <= m_RcCenter.Y + 5)
            {
                return (int)E_HANDLES.E_HANDLE_INSIDE;
            }    
            else if (point.X <= RcCentreLine.pt_end.X + 5 && point.X >= RcCentreLine.pt_end.X - 5
                   && point.Y >= RcCentreLine.pt_end.Y - 5 && point.Y <= RcCentreLine.pt_end.Y + 5)
            {
                return (int)E_HANDLES.E_HANDLE_EAST;// E_HANDLE_EAST,3        
            }
            else
            {
                return 0;
            }
        }
        public double jiaoduAndxiangxian(double x_temp, double y_temp)//角度和象限
        {
            double retTheta = 0;
            if (x_temp > 0 && y_temp > 0)
            {
                return retTheta = Math.Atan2(y_temp, x_temp);
            }
            else if (x_temp > 0 && y_temp == 0)
            {
                return retTheta = 0;
            }
            else if (x_temp < 0 && y_temp > 0)
            {
                return retTheta = Math.Atan2(y_temp, x_temp);
            }
            else if (x_temp == 0 && y_temp > 0)
            {
                return retTheta = 3.1415926 / 2.0;
            }
            else if (x_temp < 0 && y_temp < 0)
            {
                return retTheta = 2 * 3.1415926 + Math.Atan2(y_temp, x_temp);
            }
            else if (x_temp < 0 && y_temp == 0)
            {
                return retTheta = 3.1415926;
            }
            else if (x_temp > 0 && y_temp < 0)
            {
                return retTheta = 2 * 3.1415926 + Math.Atan2(y_temp, x_temp);
            }
            else if (x_temp == 0 && y_temp < 0)
            {
                return retTheta = 3 * 3.1415926 / 2.0;
            }
            else { return retTheta; }
        }
        public double m_jiaodu = 0;
        public void DragXYandRotate(PointF point)//改变centreline终点(x,y),角度
        {
            double fenziY, fenmuX;
            RcCentreLine.updatePend(point);
            fenziY = (RcCentreLine.pt_end.Y - RcCentreLine.pt_start.Y);
            fenmuX = RcCentreLine.pt_end.X - RcCentreLine.pt_start.X;
            double thetatheta1 = 0;
            thetatheta1 = jiaoduAndxiangxian(fenmuX, fenziY);

            double DeltaTheta1 = 0;       
            m_jiaodu = DeltaTheta1 = thetatheta1;
            updateRoi((float)DeltaTheta1);  //更新相关      
        }
        public void RoiReset(float deltaChang, float deltaKuan)//线图像工具重置
        {         
            PointF start = new PointF(RcCentreLine.pt_start.X, RcCentreLine.pt_start.Y);
            PointF end = new PointF(RcCentreLine.pt_start.X + 60 + deltaChang, RcCentreLine.pt_start.Y);
            RcCentreLine = new mg_line(start, end);
            m_RcCenter = new PointF((start.X + end.X) / (float)2, (start.Y + end.Y) / (float)2);      
            start = new PointF(RcCentreLine.pt_start.X, RcCentreLine.pt_start.Y - 30 - deltaKuan / (float)2);
            end = new PointF(RcCentreLine.pt_start.X, RcCentreLine.pt_start.Y + 30 + deltaKuan / (float)2);
            startLine = new mg_line(start, end);              
        }
        public float getLineLength(mg_line templine)//获取线长度
        {
            float xx = templine.pt_start.X - templine.pt_end.X;
            float yy = templine.pt_start.Y - templine.pt_end.Y;
            return (float)Math.Sqrt(xx * xx + yy * yy);
        }
        public void updateRoi(float rotationAngle)//更新我们设计的线图像工具
        {
            //置零后,再旋转这么多度。20160622也就不需要delta增量
            float chang = getLineLength(RcCentreLine);//获取直线长度
            float kuan = getLineLength(startLine);//获取直线宽度
            chang = chang - 60;//原来长度60
            kuan = kuan - 60;//原来宽度60
            RoiReset(chang, kuan);//怎样保持已更改后的大小

            // double k1;
            RcCentreLine.Rotate(RcCentreLine.pt_start, rotationAngle);
            startLine.Rotate(RcCentreLine.pt_start, rotationAngle);   

            //m_RcCenter
            PointF start = (RcCentreLine.pt_start);
            PointF end = (RcCentreLine.pt_end);
            m_RcCenter = new PointF((start.X + end.X) / (float)2, (start.Y + end.Y) / (float)2);  
        }
        public void Drag(PointF point)//拖动线图像工具
        {
            PointF delta = new PointF(point.X - m_RcCenter.X, point.Y - m_RcCenter.Y);
            RcCentreLine.Move(delta);

            startLine.Move(delta);          

            this.m_RcCenter.X = point.X;
            this.m_RcCenter.Y = point.Y;          
        }    

        public void DrawLineAndRect(Graphics g, Pen p, int Dir)//画出线图像工具
        {
            g.DrawLine(p, RcCentreLine.pt_start, RcCentreLine.pt_end);
            g.DrawLine(p, startLine.pt_start, startLine.pt_end);      
            //Centre
            g.DrawRectangle(p, (int)m_RcCenter.X - 5, (int)m_RcCenter.Y - 5, 10, 10);
            //Right
            g.DrawRectangle(p, (int)RcCentreLine.pt_end.X - 5, (int)RcCentreLine.pt_end.Y - 5, 10, 10);

           }
    }

里边有一个mg_line,是什么鬼?他来源于计算机图形学基础教材,一个直线类

  public class mg_line
    {

        public PointF pt_start;
        public PointF pt_end;
        public mg_line()
        {
            pt_end = new PointF();
            pt_start = new PointF();
        }
        public mg_line(PointF pstart, PointF pend)
        {
            pt_start = pstart;
            pt_end = pend;
        }
        public void updatePstart(PointF pstart)
        {
            pt_start = pstart;
        }
        public void updatePend(PointF pend)
        {
            pt_end = pend;
        }
        public void Translate(TransMat Mat)
        {
            Mat.TransPoint(ref pt_start);
            Mat.TransPoint(ref this.pt_end);
        }
        public void Move(PointF ZhiDingDian)
        {
            TransMat M=new TransMat();
            M.Movement(ZhiDingDian.X, ZhiDingDian.Y);
            this.Translate(M);
        }
        public void Scale(PointF pBase, double xScale, double yScale)
        {
            TransMat M = new TransMat();
            M.Scale(xScale, yScale);
            this.Translate(M);
        }
        public void Rotate(PointF pBase, double angle)
        {
            TransMat M = new TransMat();
            M.RotateBase(angle, pBase);
            this.Translate(M);
        }
    }

TransMat是什么鬼?他来源于计算机图形学基础教材,一个矩阵变换类

  public class TransMat
    {           
        const double PI = 3.1415926;
        public double[,] Mat = new double[3, 3];
        public TransMat()
        {
            int i, j;
            for (i = 0; i < 3; i++)
                for (j = 0; j < 3; j++)
                {
                    if (i == j) Mat[i,j] = 1;
                    else Mat[i,j] = 0;
                }
        }
        public void FuZhiToMat(TransMat scrMat)
        {
            int i, j;
            for (i = 0; i < 3; i++)
                for (j = 0; j < 3; j++)
                {
                    Mat[i, j] = scrMat.Mat[i, j];
                }
        }
        public void Identity()
        {
            int i, j;
            for (i = 0; i < 3; i++)
                for (j = 0; j < 3; j++)
                {
                    if (i == j) Mat[i, j] = 1;
                    else Mat[i, j] = 0;
                }
        }
      public  void Multiply(TransMat scrMat)
        {
            int i, j, k;
            double[,] M=new double[3,3];
            for (i = 0; i < 3; i++)
                for (j = 0; j < 3; j++)
                {
                    M[i,j] = 0;
                    for (k = 0; k < 3; k++)
                    {
                        M[i,j] += Mat[i,k] * scrMat.Mat[k, j];
                    }
                }
            for (i = 0; i < 3; i++)
                for (j = 0; j < 3; j++)
                {
                    Mat[i,j] = M[i,j];
                }
        }
        public void Movement(double dx, double dy)
        {
            TransMat M=new TransMat();
            M.Mat[2,0] = dx;
            M.Mat[2,1] = dy;
            Multiply(M);
        }
        public void Movement(PointF pt)
        {
            TransMat M = new TransMat();
            M.Mat[2, 0] = pt.X;
            M.Mat[2, 1] = pt.Y;
            Multiply(M);
        }
        public void Scale(double sx, double sy)
        {
            TransMat M=new TransMat();
            M.Mat[0,0] = sx;
            M.Mat[1,1] = sy;
            this.Multiply(M);
        }
        public void Scale(double s)
        {
            TransMat M = new TransMat();
            M.Mat[0, 0] = s;
            M.Mat[1, 1] = s;
            this.Multiply(M);
        }
        public void Rotate(double alf)
        {
            TransMat M=new TransMat();
            M.Mat[0, 0] = M.Mat[1, 1] = Math.Cos(alf);//Math.Cos
            M.Mat[0, 1] = Math.Sin(alf);//Math.Sin
            M.Mat[1,0] = -M.Mat[0,1];
            this.Multiply(M);
        }
        public void RotateBase(double alf, PointF Base)
        {
            this.Movement(-Base.X, -Base.Y);
            this.Rotate(alf);
            this.Movement(Base.X, Base.Y);
        }
        public void LeftMultiply(TransMat scrMat)
        {
            int i, j, k;
            double[,] M = new double[3, 3];
            for (i = 0; i < 3; i++)
                for (j = 0; j < 3; j++)
                {
                    M[i, j] = 0;
                    for (k = 0; k < 3; k++)
                    {
                        M[i, j] += scrMat.Mat[i, k] * Mat[k, j];
                    }
                }
            for (i = 0; i < 3; i++)
                for (j = 0; j < 3; j++)
                {
                    Mat[i, j] = M[i, j];
                }
        }
        public void TransPoint(ref PointF sp)
        {
            double x, y;
            x = this.Mat[0,0] * sp.X + this.Mat[1,0] * sp.Y + this.Mat[2,0];
            y = this.Mat[0,1] * sp.X + this.Mat[1,1] * sp.Y + this.Mat[2,1];
            sp.X = (float)x;
            sp.Y = (float)y;
        }
    }

未完(待续.........................)

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值