сортировка изображений

258
17 января 2018, 17:18

Сравнил попарно все изображения - получается матрица чисел (для удобства сжаты до 0-254) N x N, как теперь упорядочить чтобы похожие были рядом т.е

int r[][] = {
    { 255, 100,  93 },
    { 100, 255, 113 },
    {  93, 113, 255 }};

в этом примере вроде бы правильный порядок of = 1,0,2. n-число изобр. будет меньше 100000, числа в массиве это насколько различны изображения т.е 1 строка 0/0(такие особый случай = 255), 0 и 1, 0 и 2..

1 вариант, функция поиска ищет максимально похожее место вставки; работает совсем не плохо, лучше чем полный перебор. На длинной дистанции результат вообще интересный получился, как preview или нарезка. Лучше бы конечно если 1 куском непрерывно было, а так надо соединять на границах получившиеся сцены (баг или сравнение не точное)

of.push_back(0);
for (int i = 1; i < n; i++)
{
    auto find_bm = [&](int j) {
        std::pair<int, int> m = { 0, 255 };
        for (int i = 0; i < of.size(); i++)
        {
            int _1 = of[i], x = r[j][_1],
                _2, y = x;
            if (i < of.size() - 1)
                _2 = of[i + 1], y = r[j][_2];
            if (m.second > x + y)
                m = { i, x + y };
        }
        return of.begin() + m.first + 1;
    };
    auto it = find_bm(i);
    of.emplace(it, i);
}

создание матрицы, код слишком интегрирован, надеюсь понятно так:

srcc = avs_vfbuf_t(new avs_vfbuf(_srcc, env));
cv::Ptr<cv::img_hash::ImgHashBase> func = cv::img_hash::BlockMeanHash::create();
std::vector<cv::Mat> img_hash(n);
for (int i = 0; i < n; i++)
{
    avs_vf_t srcf = srcc->get(i);
    s_vf_plane srcp = srcf->plane();
    cv::Mat img(srcp.h, srcp.w, CV_8U, srcp.p(), srcp.pitch);
    func->compute(img, img_hash[i]);
}
for (int i = 0; i < n - 1; i++)
{
    for (int j = i + 1; j < n; j++)
        r[i][j] = r[j][i] = std::min(int(func->compare(img_hash[i], img_hash[j])), 254);
}

такой вариант не работает больше чем с ~15 размером, и я не уверен что вообще правильно:

int of[] = { 0, 1, 2 };
std::pair<int, std::vector<int>> bm = { INT32_MAX, of };
do
{
    int _ = 0;
    for (int i = 1; i < n; i++)
        _ += r[of[i - 1]][of[i]];
    if (_ < bm.first)
        bm = { _, of };
} while (std::next_permutation(of.begin(), of.end()));
of = bm.second;
Answer 1

Побитовое сравнение изображений - это сродни по-атомному сравнению двух людей с целью понять похожи они или нет. И первый и второй случай не имеют смысла и будут работать только для абсолютно одинаковых объектов. Представьте - камера сняла кадр, потом сместилась на пару сантиметров (или повернулась на пару градусов) и тут же сняла второй кадр. Похожи будут картинки? Вне всякого сомнения, любой кто взглянет скажет "одинаковые", если не особо вглядываться. А побитовое сравнение даст полную туфту - никаких совпадений. Так же как и по-атомное сравнение двух близнецов даст какую-то туфту - один простыл, другой что-то не то съел, и у них будет минимум совпадений, хотя они очень-очень похожи внешне.

Есть множество приемов сравнения изображений - на основе цветового баланса (гистограммы), на основе характеристик контуров, на основе ключевых точек, и так далее. Самым распространенным (но не самым лучшим) является метод сопоставления ключевых точек - подробно с примерами в документации opencv.

Answer 2

Я считаю, что вообще попытка преобразовать кучу изображений в линейный порядок с адекватным результатом не получится. Изображения я бы стал делить на группы схожести.

такой вариант не работает больше чем с ~15 размером, и я не уверен что вообще правильно

Я вообще не понял что делает этот код. В случае уменьшения я бы попытался менять местами все изображения подряд и сохранять изменения. Однако на большом количестве изображений(как раз примерно 15) адекватной работы вряд ли удастся чего-то добиться.

И вдобавок зачем использовать int и сокращать его до 0-254 в таком уж случае логичнее uchar(хотя от этого скорость расчётов не увеличиться).

В общем советую подумать над разделением изображений на 5-10 групп схожести и потом уже их в линию. Вдобавок для создания матрицы 100 на 100 изображений надо очень много времени а на разделение на группы схожести куда меньше(не прийдётся полностью заполнять таблицу).

READ ALSO
gdb отладка многопоточного приложения

gdb отладка многопоточного приложения

здравствуйте, возникла необходимость научиться отлаживать многопоточное приложение через gdb

364
c++ UDP Win Linux

c++ UDP Win Linux

Я хочу создать обёртку над сокетами в виде 2х простых классовНа подобии QTUdp

259
отсутствуют имена функция в выводе gdb

отсутствуют имена функция в выводе gdb

Использую данную функция для вывода stacktrace

222
Как открыть Qt project из терминала Ubuntu

Как открыть Qt project из терминала Ubuntu

Создал Qt игруКогда открываю из Qt creator все нормально работает

275