matlab - दोहराया एक्स स्थिति(गैलेक्सी सर्पिल हथियार) पर वाई अंक के साथ वक्र फिटिंग



2d curve-fitting (1)

आपका असफल कारण है कि आप अपने 2 डी वक्र को फ़ंक्शन के रूप में संभालते हैं, जो कि मामला नहीं है (आपको वही x लिए अधिक y मान मिलते हैं) और यही कारण है कि फिट सही पक्ष पर विफल रहता है (जब आप गैर फ़ंक्शन क्षेत्र को दबाते हैं)।

उपाय करने के लिए आपको प्रत्येक आयाम में वक्र फिट को अलग करने की आवश्यकता है। तो आप प्रत्येक अक्ष को अलग फ़ंक्शन के रूप में फिट कर सकते हैं। इसके लिए आपको अलग फ़ंक्शन पैरामीटर (नहीं x) का उपयोग करने की आवश्यकता है यदि आप किसी भी तरह से अपने अंक का आदेश देते हैं (उदाहरण के लिए, प्रारंभ बिंदु से वक्र दूरी, या ध्रुवीय कोण से या कभी भी) तो आप सूचकांक का प्रयोग ऐसे फ़ंक्शन पैरामीटर के रूप में कर सकते हैं।

तो आपने ऐसा कुछ किया है:

y(x) = fit((x0,y0),(x1,y1),(x2,y2)...)

जो y(x) लिए एक बहुपद देता है। इसके बजाय आपको ऐसा कुछ करना चाहिए:

x(t) = fit(( 0,x0),( 1,x1),( 2,x2)...)
y(t) = fit(( 0,y0),( 1,y1),( 2,y2)...)

जहां t आपका नया पैरामीटर क्रमबद्ध सूची में बिंदु के क्रम से सख्त है। गणना और उपयोग को कम करने के लिए अधिकांश घटता श्रेणी में पैरामीटर का उपयोग करें t=<0.0,1.0> तो अगर आपको N अंक मिलते हैं तो आप प्वाइंट इंडेक्स i=<0,N-1> को इस तरह से वक्र पैरामीटर को बदल सकते हैं:

t=i/(N-1);

जब आप की योजना बनाते हैं तो आपको अपना बदलाव करना होगा

plot(x,y(x))

सेवा मेरे:

plot(x(t),y(t))

मैंने आपके कार्य के लिए सी ++ / वीसीएल में सरल एकल प्रक्षेप क्यूब का सरल उदाहरण बनाया है ताकि आप बेहतर देखें कि मेरा क्या मतलब है:

    picture pic0,pic1;
        // pic0 - source
        // pic1 - output
    int x,y,i,j,e,n;
    double x0,x1,x2,x3,xx;
    double y0,y1,y2,y3,yy;
    double d1,d2,t,tt,ttt;
    double ax[4],ay[4];
    approx a0,a3; double ee,m,dm; int di;
    List<_point> pnt;
    _point p;

    // [extract points from image]
    pic0.load("spiral_in.png");
    pic1=pic0;
    // scan image
    xx=0.0; x0=pic1.xs;
    yy=0.0; y0=pic1.ys;
    for (y=0;y<pic1.ys;y++)
     for (x=0;x<pic1.xs;x++)
      // select red pixels
      if (DWORD(pic1.p[y][x].dd&0x00008080)==0)     // low blue,green
       if (DWORD(pic1.p[y][x].dd&0x00800000)!=0)    // high red
        {
        // recolor to green (just for visual check)
        pic1.p[y][x].dd=0x0000FF00;
        // add found point to a list
        p.x=x;
        p.y=y;
        p.a=0.0;
        pnt.add(p);
        // update bounding box
        if (x0>p.x) x0=p.x;
        if (xx<p.x) xx=p.x;
        if (y0>p.y) y0=p.y;
        if (yy<p.y) yy=p.y;
        }
    // center of bounding box for polar sort origin
    x0=0.5*(x0+xx);
    y0=0.5*(y0+yy);
    // draw cross (for visual check)
    x=x0; y=y0; i=16;
    pic1.bmp->Canvas->Pen->Color=clBlack;
    pic1.bmp->Canvas->MoveTo(x-i,y);
    pic1.bmp->Canvas->LineTo(x+i,y);
    pic1.bmp->Canvas->MoveTo(x,y-i);
    pic1.bmp->Canvas->LineTo(x,y+i);
    pic1.save("spiral_fit_0.png");
    // cpmpute polar angle for sorting
    for (i=0;i<pnt.num;i++)
        {
        xx=atan2(pnt[i].y-y0,pnt[i].x-x0);
        if (xx>0.75*M_PI) xx-=2.0*M_PI; // start is > -90 deg
        pnt[i].a=xx;
        }
    // bubble sort by angle (so index in point list can be used as curve parameter)
    for (e=1;e;)
     for (e=0,i=1;i<pnt.num;i++)
      if (pnt[i].a>pnt[i-1].a)
        {
        p=pnt[i];
        pnt[i]=pnt[i-1];
        pnt[i-1]=p;
        e=1;
        }
    // recolor to grayscale gradient (for visual check)
    for (i=0;i<pnt.num;i++)
        {
        x=pnt[i].x;
        y=pnt[i].y;
        pic1.p[y][x].dd=0x00010101*((250*i)/pnt.num);
        }
    pic1.save("spiral_fit_1.png");

    // [fit spiral points with cubic polynomials]
    n =6;                               // recursions for accuracy boost
    m =fabs(pic1.xs+pic1.ys)*1000.0;    // radius for control points fiting
    dm=m/50.0;                          // starting step for approx search
    di=pnt.num/25; if (di<1) di=1;      // skip most points for speed up
    // fit x axis polynomial
    x1=pnt[0          ].x;  // start point of curve
    x2=pnt[  pnt.num-1].x;  // endpoint of curve
    for (a0.init(x1-m,x1+m,dm,n,&ee);!a0.done;a0.step())
    for (a3.init(x2-m,x2+m,dm,n,&ee);!a3.done;a3.step())
        {
        // compute actual polynomial
        x0=a0.a;
        x3=a3.a;
        d1=0.5*(x2-x0);
        d2=0.5*(x3-x1);
        ax[0]=x1;
        ax[1]=d1;
        ax[2]=(3.0*(x2-x1))-(2.0*d1)-d2;
        ax[3]=d1+d2+(2.0*(-x2+x1));
        // compute its distance to points as the fit error e
        for (ee=0.0,i=0;i<pnt.num;i+=di)
            {
            t=double(i)/double(pnt.num-1);
            tt=t*t;
            ttt=tt*t;
            x=ax[0]+(ax[1]*t)+(ax[2]*tt)+(ax[3]*ttt);
            ee+=fabs(pnt[i].x-x);                   // avg error
//          x=fabs(pnt[i].x-x); if (ee<x) ee=x;     // max error
            }
        }
    // compute final x axis polynomial
    x0=a0.aa;
    x3=a3.aa;
    d1=0.5*(x2-x0);
    d2=0.5*(x3-x1);
    ax[0]=x1;
    ax[1]=d1;
    ax[2]=(3.0*(x2-x1))-(2.0*d1)-d2;
    ax[3]=d1+d2+(2.0*(-x2+x1));
    // fit y axis polynomial
    y1=pnt[0          ].y;  // start point of curve
    y2=pnt[  pnt.num-1].y;  // endpoint of curve
    m =fabs(y2-y1)*1000.0;
    di=pnt.num/50; if (di<1) di=1;
    for (a0.init(y1-m,y1+m,dm,n,&ee);!a0.done;a0.step())
    for (a3.init(y2-m,y2+m,dm,n,&ee);!a3.done;a3.step())
        {
        // compute actual polynomial
        y0=a0.a;
        y3=a3.a;
        d1=0.5*(y2-y0);
        d2=0.5*(y3-y1);
        ay[0]=y1;
        ay[1]=d1;
        ay[2]=(3.0*(y2-y1))-(2.0*d1)-d2;
        ay[3]=d1+d2+(2.0*(-y2+y1));
        // compute its distance to points as the fit error e
        for (ee=0.0,i=0;i<pnt.num;i+=di)
            {
            t=double(i)/double(pnt.num-1);
            tt=t*t;
            ttt=tt*t;
            y=ay[0]+(ay[1]*t)+(ay[2]*tt)+(ay[3]*ttt);
            ee+=fabs(pnt[i].y-y);                   // avg error
//          y=fabs(pnt[i].y-y); if (ee<y) ee=y;     // max error
            }
        }
    // compute final y axis polynomial
    y0=a0.aa;
    y3=a3.aa;
    d1=0.5*(y2-y0);
    d2=0.5*(y3-y1);
    ay[0]=y1;
    ay[1]=d1;
    ay[2]=(3.0*(y2-y1))-(2.0*d1)-d2;
    ay[3]=d1+d2+(2.0*(-y2+y1));
    // draw fited curve in Red
    pic1.bmp->Canvas->Pen->Color=clRed;
    pic1.bmp->Canvas->MoveTo(ax[0],ay[0]);
    for (t=0.0;t<=1.0;t+=0.01)
        {
        tt=t*t;
        ttt=tt*t;
        x=ax[0]+(ax[1]*t)+(ax[2]*tt)+(ax[3]*ttt);
        y=ay[0]+(ay[1]*t)+(ay[2]*tt)+(ay[3]*ttt);
        pic1.bmp->Canvas->LineTo(x,y);
        }
    pic1.save("spiral_fit_2.png");

मैंने आपके इनपुट छवि को ओपी में प्रदान किया था। ये चरण आउटपुट हैं

सर्पिल बिंदु चयन:

ध्रुवीय कोण के अनुसार अंक:

अंतिम योग्य परिणाम:

जैसा कि आप देख सकते हैं कि फिट बहुत अच्छा नहीं है क्योंकि:

  • मैं संपूर्ण बांह के लिए एकल क्यूबिक का उपयोग करता हूं (यह पैन के लिए बहुपद या उपविभाग की बड़ी डिग्री की आवश्यकता हो सकती है)
  • मैं छवि से बिंदु निष्कर्षण का उपयोग करता हूं और वक्र मोटी है इसलिए मेरे पास एकल ध्रुवीय कोण के लिए कई बिंदु हैं (आपको मूल बिंदु मिल गया है, इसलिए कोई समस्या नहीं होनी चाहिए) मुझे एल्गिन का उपयोग करना चाहिए, लेकिन इसे जोड़ने के लिए आलसी होना चाहिए ...

सी ++ उदाहरण में मैं अपनी छवि वर्ग का उपयोग करता हूं इसलिए यहां कुछ सदस्य हैं:

  • पिक्सल में xs,ys आकार का आकार
  • p[y][x].dd पिक्सेल पर (x, y) स्थिति 32 बिट पूर्णांक प्रकार के रूप में है
  • p[y][x].db[4] पिक्सेल का उपयोग रंग बैंड (आर, जी, बी, ए)
  • p.load(filename),p.save(filename) क्या लगता है ... छवि लोड / बचाता है
  • p.bmp->Canvas GDI बिटमैप पहुंच है, इसलिए मैं GDI सामान का भी उपयोग कर सकता हूं

फिटिंग मेरे सन्निकटन खोज वर्ग द्वारा:

  • सन्निकटन खोज कैसे काम करता है

तो बस वहां से class approx नकल करें।

List<T> टेम्पलेट सिर्फ डायनामिक एरे (सूची) है:

  • List<int> q; int q[];
  • q.num तत्वों की संख्या को अंदर रखती है
  • q.add() सूची के अंत में नए खाली तत्व जोड़ता है
  • q.add(10) सूची के अंत के लिए 10 नए तत्व जोड़ता है

[टिप्पणियाँ]

जैसा कि आपके पास पहले से ही बिंदु सूची है तो आपको अंकों के लिए इनपुट छवि स्कैन करने की आवश्यकता नहीं है ... ताकि आप कोड के उस भाग को अनदेखा कर सकें ...

यदि आपको BEZIER की बजाय प्रक्षेप बहुपद चाहिए, तो आप सीधे नियंत्रण बिंदुओं को परिवर्तित कर सकते हैं:

  • इंटरपोलेशन क्यूबिक बनाम BEZIER क्यूबिक

यदि लक्ष्य वक्र रूप तय नहीं होता है तो आप सर्फिल समीकरण को कुछ पैरामीट्रिक सर्कल जैसे समांतर केंद्र और चर त्रिज्या के साथ सीधे फिट करने का प्रयास कर सकते हैं। यह अधिक सटीक होना चाहिए और फिटिंग के बिना अधिकांश मापदंडों की गणना की जा सकती है।

[संपादित करें 1] मेरा बहुपद फिटिंग का बेहतर विवरण

मैं उपरोक्त लिंक से प्रक्षेप घन का उपयोग कर रहा हूँ इन गुणों को कंट्रेट करता हूं:

  • 4 इनपुट पॉइंट के लिए p0,p1,p2,p3 , वक्र p1 ( t=0.0 ) पर शुरू होता है और p1 t=0.0 ( t=1.0 ) पर समाप्त होता है। अंक p0,p3 ( t=-1.0 और t=2.0 ) के माध्यम से पहुंच रहे हैं और पैच के बीच निरंतरता की स्थिति सुनिश्चित करते हैं। तो p1 और p1 पर व्युत्पत्ति सभी पड़ोसी पैचों के लिए समान हैं। यह BEZIER पैच को एक साथ मिलाने के समान है।

बहुपक्षीय फिट आसान है:

  1. मैंने सर्पिल एंडपॉइंट को p1,p2 सेट किया है

    इसलिए वक्र शुरू होता है और समाप्त होता है जहां यह होना चाहिए

  2. मैं p0,p3 पास p1,p2 को कुछ दूरी m तक p1,p2 हूं

    जबकि मूल बिंदुओं पर बहुपद वक्र के निकटतम मैच को याद करते हुए। आप इसके लिए औसत या अधिकतम दूरी का उपयोग कर सकते हैं। approx कक्षा में दूरी की गणना करने के लिए approx सभी काम करते हैं।

    m लिए छवि आकार के एकाधिक उपयोग यदि बहुत बड़ा है तो आप सटीकता खो देंगे (या अधिक आवर्ती और धीमी गति से चीजों की ज़रूरत है), यदि बहुत कम है तो आप उस क्षेत्र को बाध्य कर सकते हैं जहां नियंत्रण अंक होना चाहिए और फिट बेकार हो जाएगा।

    परिवर्तन प्रारंभ करना dm m का हिस्सा है और यदि बहुत कम गणना धीमी हो जाएगी। यदि उच्च होने पर आप स्थानीय न्यूनतम / अधिकतम याद कर सकते हैं जहां समाधान का गलत परिणाम हो रहा है।

    गणना को गति देने के लिए मैं अंक से चयनित 25 अंक का उपयोग कर रहा हूँ (कोई भी उन सभी का उपयोग करने की आवश्यकता नहीं है) चरण में है

आयाम अलगाव x,y वही है जो आप बस y लिए सभी x को बदलते हैं अन्यथा कोड समान है।

मेरे पास वर्तमान में एक MATLAB प्रोग्राम है जो आकाशगंगाओं से लेकर सर्पिल हथियारों की आरजीबी छवियों को लेता है और केवल सबसे बड़ा अंग घटक और भूखंडों का चयन करता है।

मैंने matlab का उपयोग करके वक्र फिटिंग टूल में उपयोग करने की कोशिश की है ताकि इसे फिट करने के लिए स्पिबल चौरसाई हो और मुझे निम्न परिणाम मिलें:

मैंने खराब परिणाम प्राप्त करने के लिए पैरामीट्रिक फ़िटिंग के साथ इंटरप 1 का प्रयोग करने की कोशिश की है।

क्या इस तरह के वक्र को फिट करने का कोई तरीका है?