сериализация — сохранение изображений с плавающей точкой в ​​переполнении стека

Я хотел понять, как я могу сохранить изображение типа float:

float * image;

Выделяется таким образом:

int size = width * height;
image = (float *)malloc(size * sizeof(float));

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

CImg<float> image("image.jpg");
int width = image.width();
int height = image.height();
int size = width*height
float * image = image.data();

Как мне сохранить эту картинку в float от .jpg или же .bmp удобочитаемый. Я думал, чтобы открыть буфер записи, но не сохранить меня, и я не могу читать из файла!

2

Решение

ну, прежде всего, вам нужно понять, что вы делаете.
вы создаете указатель на массив float

image=(float *)malloc(size* sizeof(float));

а потом ты делаешь

float * image =image.data();

который является двойным использованием image это приведет к ошибке компилятора и плохой вещи, если вы можете это сделать.

теперь вы должны читать дальше CImg Вот и посмотри что Data() возвращает указатель на первый пиксель изображения.

Теперь, когда мы установили все это, давайте перейдем к решению:
если вы хотите сохранить массив float в файл, используйте этот пример

#include <fstream.h>

void saveArray(float* array, int length);

int main()
{
float image[] = { 15.25, 15.2516, 84.168, 84356};
saveArray(floatArray, sizeof(image)/ sizeof(image[0]));

return 0;
}

void saveArray(float* array, int length)
{
ofstream output("output.txt");

for(int i=0;i<length;i++)
{
output<<array[i]<<endl;
}
}
0

Другие решения

Так как формат изображения JPEG поддерживает только 8-битные цветовые компоненты (фактически стандарт допускает 12-битную, но я никогда не видел реализацию этого), вы не можете сделать это с JPEG.

Вы можете сделать это с помощью файла .bmp. См мой ответ на вопрос с возможным способом сделать это с OpenCV библиотека. С некоторой другой библиотекой это может быть легко с файлами .bmp, потому что OpenCV предполагает 8-битные цветовые каналы, хотя, насколько я знаю, формат .bmp этого не требует.

Вам нужно сжатие? Если нет, просто напишите двоичный файл или сохраните файл в формате yml и т. Д.

Если вам нужно сжатие OpenEXR будет вариант для рассмотрения. Наверное Магия изображения будет лучшей реализацией для вас, поскольку она хорошо интегрируется с CImg. Поскольку CImg изначально не поддерживает .jpg, я подозреваю, что у вас, возможно, уже есть Image Magick.

0

Ну, я вижу из вашего кода, что вы используете только 32-битную плавающую градацию серого (нет R, G, B, только я)
так что это мои предложения:

  1. Сияние RGBE (.hdr)
    используйте 3x8bit mantisa для показателей R, G, B и 1x8bit, что дает вам только 16-битную точность.
    Но если вы используете также R, G, B, то для целей моделирования этот формат не подходит для вас. (вы теряете большую точность из-за того, что показатель степени одинаков для всех каналов)

  2. любой формат HDR не является родным, поэтому вам необходимо установить средства просмотра и написать код для чтения / записи для вашего исходного кода или использования библиотек

  3. не HDR форматы (BMP, JPG, TGA, PNG, PCX …)
    Если вы используете только оттенки серого, то это лучшее решение для вас. Эти форматы обычно 8 бит на канал, так что вы можете использовать 24-32 бит вместе для вашей единственной интенсивности. Также вы можете просматривать / редактировать эти изображения в большинстве ОС. Есть 2 способа сделать это.

    • для 32-битных изображений вы можете просто скопировать float в color = ((DWORD *) (&Col)) [0]; где col — ваш пиксель с плавающей точкой. Это проще всего без потери точности, но если вы просматриваете изображение, оно будет не очень красивым :), потому что числа с плавающей запятой хранятся не так, как целочисленные типы.

    • использование цветовой палитры. Создайте палитру цветовой шкалы от минимального до максимального возможного значения цветов вашего пикселя (чем больше цветов, тем больше точность сохраняется). затем привязать все изображение к этим значениям. после этого конвертируйте значение с плавающей запятой в индекс в вашей палитре и сохраняйте его (для сохранения) и обратно получайте значение с плавающей запятой из индекса в палитре из цвета (для загрузки) таким образом, что изображение будет отображаться аналогично тепловым изображениям … преобразование из поплавка Значение индекса / цвета RGB может быть сделано линейно (потерять много точности) или нелинейно (с помощью функций exp, log или любого другого нелинейного значения). В лучшем случае, если вы используете 24-битные пиксели и имеете масштабную палитру из всех 2 ^ 24 цветов, и вы используйте нелинейное преобразование, тогда как вы теряете только 25% точности (если вы действительно используете весь динамический диапазон с плавающей запятой, если нет, то потери меньше даже до нуля)

советы по шкале:

  • Посмотрите на цвета светового спектра, это хорошая цветовая гамма для начала (есть много простых исходных кодов, которые создают это с помощью некоторых форм Google), вы также можете использовать любые цветовые градиентные узоры.

  • Нелинейная функция должна меньше меняться в диапазоне с плавающей запятой, где вам нужно сохранять точность (диапазон, в котором может находиться большинство ваших пикселей), и сильно изменяться там, где точность не важна (+/- NaN). Обычно я использую exp, ln или tan, но вы должны масштабировать их в соответствии с палитрой цветовой гаммы.

0

Формат файла BMP довольно прост:
https://en.m.wikipedia.org/wiki/BMP_file_format

Прочитайте заголовок, чтобы определить высоту, ширину, bpp и начальный индекс данных. А затем просто начните заполнять свой массив с плавающей точкой, приведя значения пиксельных каналов к числу с плавающей точкой (начиная с индекса, указанного в заголовке), по ширине. Когда вы достигнете модуля указанной ширины, перейдите к следующей строке в массиве.

JPG декодирование является более сложным. Я бы посоветовал не пытаться сделать это самостоятельно.

0

Если вы хотите сохранить значения с плавающей запятой, вам нужно использовать формат, который их поддерживает — это не JPEG и не BMP. Наиболее вероятные варианты:

  • TIFF — который требует библиотеки для записи

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

  • PFM (Portable Float Format), который является наименее распространенным форматом знаменателя, в том же духе, что и формат PFM. Формат NetPBM и который описан Вот.

Хорошая новость в том, что CImg опоры PFM не требует дополнительных библиотек. Так что ответ на ваш вопрос очень прост:

#include "CImg.h"using namespace cimg_library;
int main() {
CImg<float> image("image.png");
image.normalize(0.0,1.0);
image.save_pfm("result.pfm");
}

Если вы хотите просмотреть свое изображение позже, ImageMagick понимает все вышеперечисленные форматы и может конвертировать любой из них во что-либо еще:

convert result.pfm image.jpg       # convert PFM to JPG
convert result.pfm image.png       # convert PFM to PNG
convert result.tif image.bmp       # convert TIF to BMP

Ключевые слова: CImg, C ++, C, с плавающей запятой, с плавающей запятой, изображение, обработка изображений, сохранение в формате с плавающей запятой, реальное, сохранение в виде реального, 32-битный, PFM, Portable Float Map

0
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector