基于形状匹配原始版放出来(给有用的人参考2)

avatar
作者
筋斗云
阅读量:3

我们仍然讲学习。

昨天已经把80万像素1024*768的图像变成256*192图像了,并且使用iir高斯平滑保留了特征。

下面做的就是用roi把特征图扣出来,也就是所谓的模板,你在原图中的roi假定是200*200,那么在256*192中,就变成50*50了.要注意,我们昨天调用了一个函数非极大值抑制,实质是canny结果:

   public byte[] 非极大抑制黑中白202210261519(byte[] gaosbuffer, int chang, int gao)//这个buffer已经gaos过了
        {//这个版本非常精彩,自己又一次突破自己202210172008
            int hh = gao;
            int ww = chang;
            double[] 梯度幅值;
            梯度幅值 = new double[ww * hh];
            double[] gy = new double[ww * hh];
            double[] gx = new double[ww * hh];
            double[] 梯度角 = new double[ww * hh];
            byte[] 输出图像 = new byte[ww * hh];
            double maxM = 0;
            for (int i = 1; i < (hh - 1); i++)
            {
                for (int j = 1; j < (ww - 1); j++)
                {
                    int fangbian1 = i * ww + j;

                    // 3,此处改为 sobelx,sobely20220327
                    double Grady = gaosbuffer[fangbian1 - 1 - ww] + 2 * gaosbuffer[fangbian1 - ww] + gaosbuffer[fangbian1 - ww + 1]
                        - gaosbuffer[fangbian1 + ww - 1] - 2 * gaosbuffer[fangbian1 + ww] - gaosbuffer[fangbian1 + ww + 1];

                    double Gradx = gaosbuffer[fangbian1 - ww + 1] + 2 * gaosbuffer[fangbian1 + 1] + gaosbuffer[fangbian1 + ww + 1]
                         - gaosbuffer[fangbian1 - ww - 1] - 2 * gaosbuffer[fangbian1 - 1] - gaosbuffer[fangbian1 + ww - 1];

                    梯度幅值[fangbian1] = Math.Sqrt(Gradx * Gradx + Grady * Grady);
                    if (梯度幅值[fangbian1] > maxM) maxM = 梯度幅值[fangbian1];
                    // 4,这个函数博客里边有jiaoduAndxiangxian
                    梯度角[fangbian1] = jiaoduAndxiangxian(Gradx, Grady) * 180 / Math.PI;//角度,用弧度的话,速度效率高20221018

                    gx[fangbian1] = Gradx;
                    gy[fangbian1] = Grady;
                }
            }

            globmaxM = maxM;
            //5,非极大值抑制

            double g1 = 0, g2 = 0, g3 = 0, g4 = 0;
            double dTmp1 = 0.0, dTmp2 = 0.0;
            double dWeight = 0.0;
            double[] 非极大值抑制后图像 = new double[ww * hh];
            for (int i = 1; i < (ww - 1); i++)
            {
                for (int j = 1; j < (hh - 1); j++)
                {
                    int fangbian = j * ww + i;
                    if (梯度幅值[fangbian] == 0)
                    {
                        非极大值抑制后图像[fangbian] = 0;
                    }
                    else
                    {
                        //材///   
                        ///       g1  g2                  /   
                        ///           C                   /   
                        ///           g4  g3              /   
                        ///   
                        if (((梯度角[fangbian] >= 45) && (梯度角[fangbian] < 90)) ||
                            ((梯度角[fangbian] >= 225) && (梯度角[fangbian] < 270)))//
                        {
                            g1 = 梯度幅值[fangbian - ww - 1];
                            g2 = 梯度幅值[fangbian - ww];
                            g4 = 梯度幅值[fangbian + ww];
                            g3 = 梯度幅值[fangbian + ww + 1];
                            //    if (gy[fangbian] != 0)//为什么这个是多余的?

                            //     {
                            dWeight = Math.Abs(gx[fangbian] / (gy[fangbian])); //  p->Gradx,q->Grady
                            dTmp1 = g1 * dWeight + g2 * (1 - dWeight);
                            dTmp2 = g3 * dWeight + g4 * (1 - dWeight);
                            //       }
                            //      else { }
                        }
                        //材///   
                                      g1                      /   
                        // /       g4  C   g2              /   
                        // /       g3              /   
                        // / 
                        //   else
                        if (((梯度角[fangbian] >= 135) && (梯度角[fangbian] < 180)) ||//shuipingfangxiang
                                ((梯度角[fangbian] >= 315) && (梯度角[fangbian] < 360)))//20220817
                        {   //int nPointIdx = i+j*w;

                            g3 = 梯度幅值[fangbian + ww - 1];
                            g2 = 梯度幅值[fangbian + 1];
                            g1 = 梯度幅值[fangbian - ww + 1];
                            g4 = 梯度幅值[fangbian - 1];
                            //     if (gx[fangbian] != 0)//为什么这个是多余的?
                            //       {
                            dWeight = Math.Abs(gy[fangbian] / (gx[fangbian]));   //  p->Gradx,q->Grady
                            dTmp1 = g1 * dWeight + g2 * (1 - dWeight);
                            dTmp2 = g3 * dWeight + g4 * (1 - dWeight);
                            //    }
                            //  else
                            //    {
                            //先不处理20220817
                            //    }

                        }
                        //   材///   
                         /           g2  g1              /   
                         /           C                   /   
                         /       g3  g4                  /   
                         /   
                        //else 
                        if (((梯度角[fangbian] >= 90) && (梯度角[fangbian] < 135)) ||
                                 ((梯度角[fangbian] >= 270) && (梯度角[fangbian] < 315))) //20220817
                        {  //int nPointIdx = i+j*w;
                            g2 = 梯度幅值[fangbian - ww];
                            g1 = 梯度幅值[fangbian - ww + 1];
                            g4 = 梯度幅值[fangbian + ww];
                            g3 = 梯度幅值[fangbian + ww - 1];
                            //   if (gy[fangbian] != 0)//为什么这个是多余的?

                            //  {
                            dWeight = Math.Abs(gx[fangbian] / (gy[fangbian]));  //  p->Gradx,q->Grady
                            dTmp1 = g1 * dWeight + g2 * (1 - dWeight);
                            dTmp2 = g3 * dWeight + g4 * (1 - dWeight);
                            // }
                            //  else { }
                        }
                        //材///   
                              g3              /   
                              g4  C   g2              /   
                                      g1                      /   
                         
                        //else 

                        if (((梯度角[fangbian] >= 0) && (梯度角[fangbian] < 45)) ||
                      ((梯度角[fangbian] >= 180) && (梯度角[fangbian] < 225)))//这个是45度方向
                        {  //一共四个方向,已经判断了3个方向,这个可以不必判断了
                            g1 = 梯度幅值[fangbian + ww + 1];
                            g2 = 梯度幅值[fangbian + 1];
                            g3 = 梯度幅值[fangbian - ww - 1];
                            g4 = 梯度幅值[fangbian - 1];
                            // if (gx[fangbian] != 0)//为什么这个是多余的?

                            //  {
                            dWeight = Math.Abs(gy[fangbian] / (gx[fangbian]));    //  
                            dTmp1 = g1 * dWeight + g2 * (1 - dWeight);
                            dTmp2 = g3 * dWeight + g4 * (1 - dWeight);
                            // }
                            //   else { }
                        }

                    }
                    if ((梯度幅值[fangbian] > dTmp1) && (梯度幅值[fangbian] > dTmp2))
                    {
                        非极大值抑制后图像[fangbian] = 梯度幅值[fangbian];//非极大值抑制后图像

                    }
                    else
                    {
                        非极大值抑制后图像[fangbian] = 0;

                    }
                }
            }
            for (int i = 0; i < hh; i++)
            {
                for (int j = 0; j < ww; j++)
                {
                    int fangbian = i * ww + j;
                    //if ((非极大值抑制后图像[fangbian] > dThrHigh))//这个值太低,有干扰20221026,启用128
                    //    if ((非极大值抑制后图像[fangbian] > 180))//这个值太低,有干扰20221026,启用128,可能180效果更好,要匹配,有著特征就好
                    if ((非极大值抑制后图像[fangbian] > maxM * 0.618f))//黄金分割了一下
                    {//在精细中,可以尝试0.667,202211041121
                        输出图像[fangbian] = 255;
                        //if (checkBox幅值默认.Checked)
                        //{ TraceEdge(i, j, dThrLow, ref 梯度幅值, ref 输出图像, ww); }
                        //else
                        //{ TraceEdge(i, j, dThrLow, ref 非极大值抑制后图像, ref 输出图像, ww); }

                          TraceEdge(i, j, dThrLow, ref 梯度幅值, ref 输出图像,ww);  //梯度幅值版本20221017第一版本
                         TraceEdge(i, j, dThrLow, ref 非极大值抑制后图像, ref 输出图像, ww);  //第二版本20221018,这两个版本效果都可以
                    }
                }
            }
            //for (int w2b = 0; w2b < hh * ww; w2b++)
            //    输出图像[w2b] = (byte)(255 - 输出图像[w2b]);

            return 输出图像;
        }

你可以看到,我很多值限定死了,这是很有意义的,首先他是尝试过后定下来的,即经验值,另外,不变就很稳定。我们抠出的图像,即学习图像就来自  return 输出图像;

下面就是抠图代码,并且记录了学习到的边(注意和线条要区别,便可以组成线条,但不是线条),也就是我们提炼了canny图像,不要整体,只要特征,这样匹配中数据量就会很小:

   //  showbuffer2pict(globgaospydoutimgN, 128, 96, pictureBox加速gaos);
            //
            pictureBoxroi.Size = new Size(256, 192);
            if (globgaospydoutimgN == null) return;
            //   roi内所有llp
            float top = m_cutImageRoi.m_RoiBase1.rcWin.Top/4f;
            float left = m_cutImageRoi.m_RoiBase1.rcWin.Left/4f;
            //float right = m_cutImageRoi.m_RoiBase1.rcWin.Right;
            //float bottom = m_cutImageRoi.m_RoiBase1.rcWin.Bottom;

            int temproiw = (int)(m_cutImageRoi.m_RoiBase1.rcWin.Width/4f+3);
            int temproih = (int)(m_cutImageRoi.m_RoiBase1.rcWin.Height/4f+3);//si`she*wu*ru`dao*zhi`dejia-san-+3

            int mod = temproiw % 4;//解决四位对齐问题20150716
            temproiw = temproiw + (4 - mod) % 4;
            //  _RoiH = Convert.ToInt32(textBoxH.Text);
            int temproiX = (int)left;
            int temproiY = (int)top;

            byte[] roiImage = new byte[temproiw * temproih];
            //   unsafe
            {
                for (int i = 0; i < temproih; i++)
                    for (int j = 0; j < temproiw; j++)
                    {
                        roiImage[i * temproiw + j] = globgaospydoutimgN[((i + temproiY) * 128 + j + temproiX)];
                    }

            }

            List<List<Point>> llpgaos12896roi = new List<List<Point>>();
            //  llpgaos12896.Clear();
            int ww = temproiw; int hh = temproih;
            // ww = temproiw;  hh = temproih;
            for (int i = 0; i < hh; i++)//****染色算法必须202209091600染色算法也隐含了白底黑斑
            {//所以这里必须反色处理,负责没有结果//202209091606
                roiImage[i * ww + 0] = 0;
                roiImage[i * ww + ww - 1] = 0;
            }
            for (int j = 0; j < ww; j++)
            {
                roiImage[0 * ww + j] = 0;
                roiImage[(hh - 1) * ww + j] = 0;
            }
            染色算法黑中白(ref llpgaos12896roi, ref roiImage, ww, hh);//在边界崩溃了20220831
            if (llpgaos12896roi.Count == 0) return;
            showbuffer2pict(roiImage, ww, hh, pictureBoxroi);//roi内线条被染色为240

            /
            //质心还是要找,可能会用到,llp可以合并在一起用。202210261700
         
            hebingllp.Clear();
            for (int i = 0; i < llpgaos12896roi.Count; i++)
            {
                for (int j = 0; j < llpgaos12896roi[i].Count; j++)
                {
                    hebingllp.Add(llpgaos12896roi[i][j]);//找出x,y中最大,最小,差值加一来确认宽和高202210261709
                }
            }
            //0度匹配
            List<float> arr = new List<float>();

            for (int i = 0; i < hebingllp.Count; i++)
            {
                arr.Add(hebingllp[i].X);
            }
            // 以上四个x,找出最大和最小,画出两条线;
            float min = arr[0]; float max = arr[0];
            for (int i = 0; i < arr.Count; i++)
            {
                if (min > arr[i])
                {
                    min = arr[i];
                }
                if (max < arr[i])
                {
                    max = arr[i];
                }
            }

            arr = new List<float>();
            // 同样四个y,找出最大和最小,画出两条线;
            for (int i = 0; i < hebingllp.Count; i++)
            {
                arr.Add(hebingllp[i].Y);
            }
            float min1 = arr[0]; float max1 = arr[0];
            for (int i = 0; i < arr.Count; i++)
            {
                if (min1 > arr[i])
                {
                    min1 = arr[i];
                }
                if (max1 < arr[i])
                {
                    max1 = arr[i];
                }
            }
              
            匹配www = (int)Math.Abs(max - min);//两个x值
            //匹配www = (int)Math.Abs(max - min)+1;//两个x值
            匹配www = (int)Math.Abs(max - min) + 2 + 1 + 1;//两个x值//202210270838
           匹配qidianX = (int)min - 2;
             
            匹配hhh = (int)Math.Abs(max1 - min1);//两个y值//左顶(min,min1)及右底(max,max1)
            //匹配hhh = (int)Math.Abs(max1 - min1)+1;
            匹配hhh = (int)Math.Abs(max1 - min1) + 2 + 1 + 1;
           匹配qidianY = (int)min1 - 2;//已经改进,可以接受0,0;不能接受-1000//202211040955

           min和min1有都等于0的情形,所以不能赋值为零,为-1来判断吧,0,0值有可能是ok状况,匹配qidianY的条件要放宽
           hebingllp1.Clear();
           for (int t = 0; t < hebingllp.Count; t++)
           {
               hebingllp1.Add(new Point(hebingllp[t].X - 匹配qidianX, hebingllp[t].Y - 匹配qidianY));//这样处理的好处是与匹配www* 匹配hhh一致。202210261924
           }
            //
         
            buttonmatchlearning.Enabled = false;

要注意的是,我们找了特征的最小外接矩形,显然他比抠图的roi要小,这也是为匹配减少数据量,匹配中,就用这个矩形,遍历整个256*192图像。

其实,roi矩形也是可以的,矩形大,搜索次数减少,矩形小,搜索次数多,你要衡量一下,我这里没用roi矩形。

学习就算完了,下面讲匹配,待续。。。

广告一刻

为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!