WedX - журнал о программировании и компьютерных науках

Преобразование cv::Mat в беззнаковые целые пиксели

Я пытаюсь преобразовать cv::Mat в буферное изображение без знака int, преобразование не работает, я получаю черное изображение

    Mat srcIm, edges;
    srcIm = imread("15016889798859437.jpg");
    cv::cvtColor(srcIm, srcIm, cv::COLOR_BGR2RGB);
    unsigned int *finalSrc = new unsigned int[srcIm.rows*srcIm.cols*3];

    unsigned char *input = (unsigned char*)(srcIm.data);

        for (int i = 0; i < srcIm.rows; i++) {
            for (int j = 0; j < srcIm.cols; j++) {
                 int r, g, b;
                r = input[srcIm.step * j + i];
                g = input[srcIm.step * j + i + 1];
                b = input[srcIm.step * j + i + 2];

                int rgb = ((r & 0x0ff) << 16) | ((g & 0x0ff) << 8) | (b & 0x0ff);

                finalSrc[i+ j*srcIm.rows] = rgb;
            }
        }

        cv::Mat videoFrame(srcIm.rows, srcIm.cols, CV_32SC1, finalSrc);

ОБНОВЛЕННЫЙ КОД:

Следуя комментариям, я исправил ошибки, но все равно получаю белое изображение.

unsigned int *finalSrc = new unsigned int[srcIm.rows*srcIm.cols];

    unsigned char *input = (unsigned char*)(srcIm.data);

    int cn = srcIm.channels();

    for (int i = 0; i < srcIm.rows; i++)
    {
        for (int j = 0; j < srcIm.cols; j++)
        {
            int r, g, b;

            r = input[(i * srcIm.cols * srcIm.channels()) + (j*srcIm.channels()) + 0];
            g = input[(i * srcIm.cols * srcIm.channels()) + (j*srcIm.channels()) + 1];
            b = input[(i * srcIm.cols * srcIm.channels()) + (j*srcIm.channels()) + 2];

            int rgb = ((r & 0x0ff) << 16) | ((g & 0x0ff) << 8) | (b & 0x0ff);

        }
    }

    cv::Mat videoFrame(srcIm.rows, srcIm.cols, CV_32S, finalSrc);


    imshow("v", videoFrame);
23.08.2017

  • Чтобы получить доступ к определенному пикселю в массиве внутри циклов too, чьи переменные i и j, вы должны image[(i * image.cols * image.channels)+(j*image.channels)+desiredChannel] 23.08.2017
  • Вы имеете в виду назначение finalSrc? 23.08.2017
  • cvtColor довольно бесполезен — вы можете просто поменять местами r на b в цикле. finalSrc кажется в 3 раза больше необходимого размера. Индексация ввода также совершенно не нужна, вы можете просто перебирать элементы. 23.08.2017
  • @DanMašek Можете ли вы опубликовать ответ с этими настройками? 23.08.2017
  • Нет, r, g, b назначение 23.08.2017
  • opencv не поддерживает тип unsigned int, только подписанный int (.convertTo(CV_32S)) 23.08.2017
  • @Micka Я конвертировал cv::Mat videoFrame(srcIm.rows, srcIm.cols, CV_32S, finalSrc); но все же я получаю белое изображение 23.08.2017
  • Я обновил код в отношении комментариев, но все равно получаю белое изображение. 23.08.2017
  • как я уже сказал, openCV не допускает UNSIGNED int, только подписанный int. В вашем вопросе совершенно неясно, чего вы хотите достичь, если вы хотите, чтобы один int представлял значения RGB, вместо этого используйте CV_8UC4, кодируя 1 int как значения BGRA. В настоящее время вы создаете одноканальный мат, который использует неинициализированные значения памяти. 23.08.2017

Ответы:


1

ИМХО есть несколько возможностей упростить код.

  1. Отбросьте cvtColor. Вы все равно перебираете элементы, поэтому просто поменяйте местами r и b в теле цикла, и вы сможете избежать преобразования.

  2. Массив finalSrc в 3 раза больше необходимого размера. Это один канал Mat, поэтому вам нужно всего srcIm.rows * srcIm.cols элементов.

  3. Нет необходимости в такой сложной индексации. Mat имеют одинаковую форму, поэтому вы можете просто перебирать элементы.

  4. Даже не повторяйте, используйте вместо этого алгоритм — std::transform хорошо подходит для этого.

  5. #P6# <блочная цитата> #P7# #P8#

Примечание. Я использую «напечатанные» Mat (например, cv::Mat3b, cv::Mat1i). Они «знают» содержащийся в них тип данных, что несколько упрощает их использование.

Примечание. Я заполняю входное изображение последовательностью значений. Первый пиксель будет иметь (B=0, G=1, R=2), второй (B=3, G=4, R=5) и так далее. Это упрощает проверку результатов.


Код:

#include <opencv2/opencv.hpp>
#include <numeric>

int main()
{
    // Generate a sample image.
    cv::Mat3b srcIm(4, 4);
    std::iota(srcIm.data, srcIm.data + srcIm.rows * srcIm.cols * 3, 0);

    cv::Mat1i videoFrame(srcIm.rows, srcIm.cols);

    // Perform the conversion
    std::transform(srcIm.begin(), srcIm.end(), videoFrame.begin()
        , [](cv::Vec3b const& v) {
            return v[0] | (v[1] << 8) | (v[2] << 16);
        });

    // Display results
    for (auto const& v : videoFrame) {
        std::cout << std::setw(6) << std::setfill('0') << std::hex << v << "\n";
    }

    return 0;
}

Выход:

020100
050403
080706
0b0a09
0e0d0c
11100f
141312
171615
1a1918
1d1c1b
201f1e
232221
262524
292827
2c2b2a
2f2e2d

Вы упоминаете, что хотите получить результат в виде массива. Тот же принцип будет применяться.

std::unique_ptr<unsigned int[]> result(new unsigned int[srcIm.rows * srcIm.cols]);

std::transform(srcIm.begin(), srcIm.end(), result.get()
    , [](cv::Vec3b const& v) {
        return v[0] | (v[1] << 8) | (v[2] << 16);
    });
23.08.2017
  • Дело в том, что я хочу сохранить cv::Mat в unsigned int [] 23.08.2017
  • @andre Будет применяться тот же принцип, просто замените videoFrame. 23.08.2017
  • @andre В каком смысле это не работает? Можно поподробнее, пожалуйста? К сожалению, у меня нет копии VS2017, чтобы протестировать его, но он определенно кажется немного странным, он уже давно является частью С++. Возможно, я пропустил включение, оно должно быть в <algorithm>. 23.08.2017
  • Это проблема безопасности, поэтому я отключил предупреждение. Но спасибо за ответ. Можно ли увидеть результат в cv::Mat, я знаю, что это невозможно, но я преобразовал видеофрейм в CV_32S 23.08.2017
  • вопрос, как рассчитать шаг для cv::Mat 24.08.2017
  • @andre Пожалуйста, опубликуйте это как новый вопрос. 24.08.2017
  • stackoverflow .com/questions/45849832/ 24.08.2017
  • Новые материалы

    Объяснение документов 02: BERT
    BERT представил двухступенчатую структуру обучения: предварительное обучение и тонкая настройка. Во время предварительного обучения модель обучается на неразмеченных данных с помощью..

    Как проанализировать работу вашего классификатора?
    Не всегда просто знать, какие показатели использовать С развитием глубокого обучения все больше и больше людей учатся обучать свой первый классификатор. Но как только вы закончите..

    Работа с цепями Маркова, часть 4 (Машинное обучение)
    Нелинейные цепи Маркова с агрегатором и их приложения (arXiv) Автор : Бар Лайт Аннотация: Изучаются свойства подкласса случайных процессов, называемых дискретными нелинейными цепями Маркова..

    Crazy Laravel Livewire упростил мне создание электронной коммерции (панель администратора и API) [Часть 3]
    Как вы сегодня, ребята? В этой части мы создадим CRUD для данных о продукте. Думаю, в этой части я не буду слишком много делиться теорией, но чаще буду делиться своим кодом. Потому что..

    Использование машинного обучения и Python для классификации 1000 сезонов новичков MLB Hitter
    Чему может научиться машина, глядя на сезоны новичков 1000 игроков MLB? Это то, что исследует это приложение. В этом процессе мы будем использовать неконтролируемое обучение, чтобы..

    Учебные заметки: создание моего первого пакета Node.js
    Это мои обучающие заметки, когда я научился создавать свой самый первый пакет Node.js, распространяемый через npm. Оглавление Глоссарий I. Новый пакет 1.1 советы по инициализации..

    Забудьте о Matplotlib: улучшите визуализацию данных с помощью умопомрачительных функций Seaborn!
    Примечание. Эта запись в блоге предполагает базовое знакомство с Python и концепциями анализа данных. Привет, энтузиасты данных! Добро пожаловать в мой блог, где я расскажу о невероятных..


    Для любых предложений по сайту: [email protected]