Ho un'immagine a 8 bit. Per ogni pixel, ho bisogno di calcolare la sua posizione ordinale nella riga corrente. Ad esempio, se la riga è:Serve aiuto per vettorizzare questo codice
32 128 16 64,
poi bisogno il risultato:
1 3 0 2,
poiché 32 è il primo valore più alto nella riga, 128 è 3 ° posto, 16 è 0th alta e 64 è il 2 ° più alto.
Ho bisogno di ripetere la procedura sopra per tutte le righe dell'immagine. Ecco il codice non vettorizzati:
for (int curr = 0; curr < new_height; ++curr)
{
vector<pair<unsigned char, char> > ordered;
for (char i = 0; i < 4; ++i)
{
unsigned char val = luma24.at<unsigned char>(curr, i);
ordered.push_back(pair<unsigned char, char>(val, i));
}
sort(ordered.begin(), ordered.end(), cmpfun);
for (int i = 0; i < 4; ++i)
signature.at<char>(curr, ordered[i].second) = i;
}
luma24
è l'immagine a 8 bit che sto leggendo da, e ha new_height
righe e 4 colonne. signature
è un'immagine firmata della stessa dimensione (ignora la differenza di segno per ora, poiché non è rilevante) - è dove sto memorizzando il risultato. cmpfun
è una funzione comparativa banale.
ho cercato di vettorizzare il codice di cui sopra e ha ottenuto questo:
Mat ordinal;
luma24.convertTo(ordinal, CV_16UC1, 256, 0);
Mat sorted = ordinal.clone();
for (int i = 0; i < 4; ++i)
ordinal(Range::all(), Range(i, i+1)) += i;
cv::sort(ordinal, sorted, CV_SORT_EVERY_ROW | CV_SORT_ASCENDING);
bitwise_and(sorted, Scalar(0x00ff), ordinal);
Mat ordinal8;
ordinal.convertTo(ordinal8, CV_8SC1, 1, 0);
ordinal8.copyTo(signature(Range::all(), Range(0, 4)));
ho dovuto mettere in valigia il valore a 8 bit e l'ordinale 8-bit in un singolo canale a 16 bit poiché OpenCV non esegue ordina per immagini multicanale. Questo è quasi ciò di cui ho bisogno, ma non del tutto. Per l'ingresso ad esempio, mi dà:
2 0 3 1
in quanto il valore più basso si trova nella seconda colonna, di prossima più basso è nella colonna 0, ecc Come posso fare per convertire questo per il risultato che ho bisogno, senza accedere a ciascun pixel individualmente?
In sostanza, ho bisogno di vettorizzare in qualche modo questo:
uint8_t x[] = {2, 0, 3, 1};
uint8_t y[4];
for (uint8_t i = 0; i < 4; ++i)
y[x[i]] = i;
dove x
è il risultato intermedio mio attuale codice vettorializzare mi dà e y
è il risultato che voglio.
Si può fare?
Solo per chiarimenti (non ho ancora una risposta) - Che cosa vuoi fare se hai più pixel con lo stesso valore? Dovrebbero essere tutti lo stesso ordinale? –
Off topic: Che coincidenza, l'altro giorno stavo leggendo il codice sorgente [ffmpeg tutorial] (https://github.com/mpenkov/ffmpeg-tutorial) che avevi speculato su github. L'URL ha smesso di funzionare quindi sono andato sul tuo profilo nel caso in cui lo avessi rinominato, ma suppongo che tu l'abbia rimosso, e in questo momento ho riconosciuto il tuo avatar per caso. –
In questa forma è quasi impossibile. Quali vincoli ci sono? per esempio. x [] ha sempre 4 elementi di larghezza? dovrebbe invece essere uint8_t? –