У меня есть 8-битное изображение. Для каждого пикселя мне нужно определить его порядковое положение в текущей строке. Например, если строка:
32 128 16 64,
тогда мне нужен результат:
1 3 0 2,
так как 32 является 1-м по величине значением в строке, 128 — 3-м по величине, 16 — 0-м по величине и 64 — 2-м по величине.
Мне нужно повторить описанную выше процедуру для всех строк изображения. Вот не векторизованный код:
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 — это 8-битное изображение, из которого я читаю, и оно имеет new_height строк и 4 столбца. signature - это подписанное изображение того же размера (пока не обращайте внимания на разницу в знаке, поскольку это не имеет значения) - здесь я сохраняю результат. cmpfun — тривиальная функция сравнения.
Я попытался векторизовать приведенный выше код и получил это:
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)));
Мне пришлось упаковать 8-битное значение и 8-битный порядковый номер в один 16-битный канал, поскольку OpenCV не выполняет сортировку многоканальных изображений. Это почти то, что мне нужно, но не совсем. Для примера ввода это дает мне:
2 0 3 1
поскольку наименьшее значение находится во 2-м столбце, следующее наименьшее — в 0-м столбце и т. д. Как мне преобразовать это в нужный мне результат без доступа к каждому пикселю по отдельности?
По сути, мне нужно как-то векторизовать это:
uint8_t x[] = {2, 0, 3, 1};
uint8_t y[4];
for (uint8_t i = 0; i < 4; ++i)
y[x[i]] = i;
где x — промежуточный результат, который дает мой текущий векторизованный код, а y — результат, который я хочу.
Можно ли это сделать?
uint8_tлучше -- мне просто было лень. - person mpenkov   schedule 12.03.2013cv:sortIdx()? - person Adi Shavit   schedule 24.04.2013