2012-07-31 16 views
10

Jak zdefiniować tablice w C++/Otwórz CV tak jak w Matlabie?Macierze typu Matlab w C++

na przykład:

x=a:b:c; 

lub

y=linspace(a,b,n); 
+0

Dobra odpowiedź na podobne pytanie [tutaj] (https://stackoverflow.com/a/27030598/3079302). – iled

Odpowiedz

9

Skorzystaj z poprzednich odpowiedzi, aby uzyskać ogólne odpowiedzi na swoje pytanie.

szczególności, aby rozwiązać te dwa przykłady, które można wymienić, jest tu jakiś równoważny kod C++ przy użyciu wektorów do dynamicznego generowania tablic pan wspomniał (nie testowane):

#include <vector> 
using std::vector; 

vector<double> generateRange(double a, double b, double c) { 
    vector<double> array; 
    while(a <= c) { 
     array.push_back(a); 
     a += b;   // could recode to better handle rounding errors 
    } 
    return array; 
} 

vector<double> linspace(double a, double b, int n) { 
    vector<double> array; 
    double step = (b-a)/(n-1); 

    while(a <= b) { 
     array.push_back(a); 
     a += step;   // could recode to better handle rounding errors 
    } 
    return array; 
} 
+1

przedalokacja wypełnia 'tablicę' wartościami 'n', następnie' push_back' dołącza do wartości 'n' do końca, więc powinieneś upuścić prealokację – YuppieNetworking

+0

dzięki @YuppieNetworking. Myliłem języki, myśląc, że konstruktor przydzielony bez wypełniania. Usunąłem wstępną alokację, ponieważ używam 'push_back'. – mattgately

+0

@mattgately, możesz użyć funkcji 'reserve', aby była bardziej efektywna. –

3

OpenCV oferuje kilka funkcji, które są podobne do Matlab, ale ich liczba jest bardzo ograniczona.

Można

cv::Mat a = cv::Mat::eye(5); 
cv::Mat b = cv::Mat::zeros(5); 
cv::Mat img = cv::imread("myGorgeousPic.jpg"); 
cv::imwrite(img, "aCopyOfMyGorgeousPic.jpg"); 

Obsługuje również diag()

Ale dla większości z tej skomplikowanej funkcjonalności Matlab jak linspace lub magic czy cokolwiek innego, nie ma korespondent w OpenCV, głównie dlatego OpenCV nie jest matematyka pakiet, ale komputerowa wizja. Jeśli potrzebujesz jakiejś konkretnej funkcji, możesz sklonować ją w projekcie (pisz ją samodzielnie).

3

Niestety, C++ nie ma wbudowanego w nią nic, aby umożliwić tego rodzaju inicjalizację macierzy. Obsługuje tablice wielowymiarowe, ale musisz sam zainicjalizować każdy element. C++ jest językiem niższego poziomu niż Matlab i wymaga znacznie więcej pracy, aby napisać funkcjonalność do tworzenia i inicjowania zmiennej typu matrix.

Powiedziawszy, że istnieje wiele bibliotek dostępnych do użycia z C++, które ułatwiają obliczenia numeryczne, niż gdybyś sam próbował je napisać. Jeśli chcesz rozważyć korzystanie z bibliotek, zapoznaj się z tym linkiem, który sugeruje kilka odpowiednich: https://scicomp.stackexchange.com/questions/351/recommendations-for-a-usable-fast-c-matrix-library

1

Jest to prosta implementacja jeśli używasz openCV.

Mat linspace(double &startP,double &Endp,int &interval) 
{ 
    double spacing = interval-1; 
    Mat y(spacing,1,CV_64FC1); 
    for (int i = 0; i < y.rows; ++i) 
    { 
     y.at<double>(i) = startP + i*(Endp - startP)/spacing; 
    } 
    return y; 
} 
1
double* linspace(int xi, int xf, unsigned int n){ 
double *vec ; 
vec = new double[n]; 
float esp, falt=xf-xi; 
esp=falt/(n-1); 
vec[0]=xi; 
for(int i=1; i<n; i++) 
    vec[i]=vec[i-1]+esp; 
return vec; 
+1

Twoja odpowiedź powinna zawierać objaśnienie kodu i opis sposobu rozwiązania problemu. – AbcAeffchen

1

tutaj jest mój sprawdzony linspace bardzo podobna do wszystkich innych, ale obsługuje wszystkie przypadki:

vector<double> Utilities::Linspace(double a, double b, int n) { 
    vector<double> array; 
    double epsilon = 0.0001; 
    double step = (b-a)/(n-1); 
    if (a==b) 
    { 
     for (int i = 0; i < n; i++) 
     { 
      array.push_back(a); 
     } 
    } 
    else if (step >= 0) 
    { 
     while(a <= b + epsilon) 
     { 
      array.push_back(a); 
      a += step;   
     }  
    } 
    else 
    { 
     while(a + epsilon >= b) 
     { 
      array.push_back(a); 
      a += step;   
     }  
    } 
    return array; 
} 
+0

Klasyczny błąd dzielenia przez zero, gdy 'n = 1' ... Przesłałem kilka drobnych zmian (patrz poniżej) – champost

0

Przedłużenie @ odpowiedź Gilada powyżej dla przypadków, kiedy n=0 i n=1 ponieważ ostatni daje wzrost do podziału przez zero.

vector<double> linspace(double a, double b, int n) { 
    vector<double> array; 
    if ((n == 0) || (n == 1) || (a == b)) 
     array.push_back(b); 
    else if (n > 1) { 
     double step = (b - a)/(n - 1); 
     int count = 0; 
     while(count < n) { 
      array.push_back(a + count*step); 
      ++count; 
     } 
    } 
    return array; 
} 
+0

Twój kod nie obsługuje przypadku, gdy krok to -ve. (b> a lub b ankittie

+0

@ankittie co sprawia, że ​​tak mówisz, czy próbowałeś kodu? 'step' jest typu' double' i może być równe + ve lub -ve. – champost

1

Chciałbym dodać niewielką modyfikację kodu zaproponowanego przez mattgately.Używałem go i istnieją pewne przypadki, gdy step nie jest prawidłowo obliczone ze względu na podział zbliżenia

double step = (b-a)/(n-1); 

Właśnie dodałem niewielką liczbę do stanu while:

while(a <= b+0.00001) 

Podobnie jak to, że pracował ze mną została utworzona prawidłowa liczba interwałów.