cv :: Mat to std :: string, сериализация и десериализация, дающая ошибочный результат - PullRequest
0 голосов
/ 11 февраля 2020

Я пытаюсь использовать приведенный ниже код для сериализации и десериализации объекта cv :: Mat. Он просто записывает всех учаров в поток ostring, а затем преобразует его в строку для сериализации. Затем я десериализирую эту строку с помощью istringstream и сохраняю всех учителей в объект Mat. Тип циновки CV_8UC3 - это le git, я проверил это с помощью функции в this answer. 8UC3 - это канал тестового мата, который я даю в качестве параметра. Я знаю, что это, вероятно, неудачный способ сериализации, поэтому я открыт для лучших идей. Во всяком случае, я только 25% я sh часть изображения. Остальное отсутствует. И я получаю странное искажение цвета в середине. Выходные и входные изображения находятся под кодом. Если вам нужна дополнительная информация, не стесняйтесь спрашивать.

void dbop::serializeMat(cv::Mat operand) {

std::ostringstream srlzstrstream;
srlzstrstream << operand.rows << " " << operand.cols << " " ;
for(int i = 0; i < operand.rows; i++)
    for (int j = 0; j < operand.cols; j++)
        srlzstrstream << operand.at<uchar>(i, j);

std::string srlzdstr = srlzstrstream.str();

uchar uchoper;
int row, col;
std::istringstream desrlzstrstream(srlzdstr);

desrlzstrstream >> row;
desrlzstrstream >> col;
cv::Mat matoper(row, col, CV_8UC3);

for (int i = 0; i < row; i++) {
    for (int j = 0; j < col; j++) {
        desrlzstrstream>> uchoper;
        matoper.at<uchar>(i, j) = uchoper;
    }
}

return;
}

Это входное изображение

Это выходное изображение

РЕДАКТИРОВАТЬ

rafix07 после следования вашему совету я нашел альтернативный способ, который имеет 3 байта на пиксель. Теперь я получаю полную картину, но искажение цвета (или как оно там называется) теперь хуже, чем когда-либо. Верхние 10% я sh выходного изображения в порядке, но ниже, он идет в ад. См. Изображение ниже кода.

void dbop::serializeMat(cv::Mat operand) {
std::ostringstream srlzstrstream;
cv::uint8_t* pixelPtr = (uint8_t*)operand.data;
int cn = operand.channels();
cv::Scalar_<uint8_t> bgrPixel;

srlzstrstream << operand.rows << " " << operand.cols << " ";
for (int i = 0; i < operand.rows; i++) {
    for (int j = 0; j < operand.cols; j++) {
        bgrPixel.val[0] = pixelPtr[i * operand.cols * cn + j * cn + 0]; // B
        bgrPixel.val[1] = pixelPtr[i * operand.cols * cn + j * cn + 1]; // G
        bgrPixel.val[2] = pixelPtr[i * operand.cols * cn + j * cn + 2]; // R
        srlzstrstream << bgrPixel.val[0] << bgrPixel.val[1] << bgrPixel.val[2];
    }
}
std::string srlzdstr = srlzstrstream.str();
uchar uchoper1, uchoper2, uchoper3;
int row, col;
std::istringstream desrlzstrstream(srlzdstr);

desrlzstrstream >> row;
desrlzstrstream >> col;
cv::Mat matoper(row, col, CV_8UC3);

for (int i = 0; i < row; i++) {
    cv::Vec3b* ptr = matoper.ptr<cv::Vec3b>(i);
    for (int j = 0; j < col; j++) {
        desrlzstrstream >> uchoper1;
        desrlzstrstream >> uchoper2;
        desrlzstrstream >> uchoper3;
        ptr[j] = cv::Vec3b(uchoper1, uchoper2, uchoper3);
    }
}
return;
}

Выходное изображение после редактирования

1 Ответ

1 голос
/ 11 февраля 2020

Предположим, у вас есть:

uchar ch = 10;
ostringstream os;
os << ch;

когда вы сделаете:

std::cout << "[" << os.str() << "]" << std::endl;

вы увидите:

[
]

, потому что ostringstream обрабатывает все сохраненные значения в (без знака) char как символы (в вышеприведенном случае 10 представляет символ новой строки, и этот символ новой строки помещается в поток вместо его значения цифры c). Вы должны писать / читать целые числа с точностью не менее 16 бит. И еще одна проблема, при добавлении в поток необходимо добавить пробелы между значениями.

Итак, первое обновление:

srlzstrstream << (int)bgrPixel.val[0] << " " << (int)bgrPixel.val[1] << " " << (int)bgrPixel.val[2] << " ";

, а следующее:

uint16_t uchoper1, uchoper2, uchoper3;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...