LINUX.ORG.RU

Gray > Red/Blue (тепловизор)

 , ,


1

1

Есть Ч/Б изображение с тепловизора. Необходимо преобразовать в цветное по градации от синего к красному.

На SOF нагуглил пару примером, но сам их ещё не пробовал. Может имеется готовая библиотека для этих целей?

Если считаете, что задачу можете решить в частном порядке за символическую плату, пишите на iiiypuk@fastmail.fm, либо в Telegram: https://t.me/db_o_qp

★★★★
Ответ на: комментарий от LINUX-ORG-RU
Ответ на: комментарий от IIIypuk

Могу только такое изображение дать

подобные изображения нынешние «ИИ» могут раскрашивать в цвета близкие к естественным. И отчасти подрисовывать детали :-) Без градиентов.

Кстати давно уже. Ч/б фильмы раскрашивали на полуавтомате, а сейчас и без вмешательства человека.

MKuznetsov ★★★★★
()
Последнее исправление: MKuznetsov (всего исправлений: 1)
Ответ на: комментарий от IIIypuk

Всё это будет работать в реальном времени, где интернетов даже не планируется.

в «нереальном времени»,долго/нужно/ресурсозатратно обучать модель (нейросеть), вы ближе к теме - возможно уже готовое где-то есть и можно взять. Или методика обучения отработанная, которую достаточно повторить

А в железе : Сейчас NN-сопроцессоры уже повсюду. Одноплатник без такой фичи скоро фик найдёшь :-)

MKuznetsov ★★★★★
()
Ответ на: комментарий от rumgot

Какой нафиг пример данных? Это примитивное преобразование, самое сложное тут - это подключить libjpeg или что там чтоб исходную картинку прочитать и результат записать. А сам алгоритм это меньше 10 строчек на Си, вплоть до ОДНОЙ. Например такой:

for(i=0; i<size_x*size_y; i++,data++) { data->blue = 255 - data->blue; data->green = 0; }
firkax ★★★★★
()

mkdir pika && cd pika && touch main.lua копипаста кода love . из pika каталога

local image = nil;
local previ = nil;
local pose = {x=0,y=0};
local scal = 0;
local sx = 0;
local sy = 0;
-- настроить окно
function love.load()
    love.window.setTitle('Перетащи png картинку в это окошечко')
    love.window.setMode(800,600,{resizable=true});
end
-- получить файл
function love.filedropped(file)
    --love.filesystem.load("main.lua")()
    local filename = file:getFilename();
    local file_ext = filename:match("%.%w+$")
    if file_ext == '.png' then
         image = love.image.newImageData(file);
    end

end
-- обработать файл
function love.update()
    if image and previ ~= image then
       local width, height = image:getDimensions();
        for y = 1, height do
            for x = 1, width do
                local r, g, b, a = image:getPixel(x-1, y-1);
                r,g,b,a = image_gray_to_color(r,g,b,a);
                image:setPixel( x-1, y-1, r, g, b, a );
            end
        end
       image = love.graphics.newImage(image);
       previ = image;
       local w,h = love.window.getMode()
       sx,sy = w/image:getWidth(),h/image:getHeight();
       pose.x = 0;
       pose.y = 0;
       scal = 0;
    end

end
-- перемещение
function love.mousemoved(x,y,dx,dy)
    if love.mouse.isDown(1) then
       if dx ~= 0 then pose.x = pose.x + dx; end
       if dy ~= 0 then pose.y = pose.y + dy; end
    end
end

-- масштабирование
function love.wheelmoved(x,y)
    scal = scal + y * 0.1;
end
-- преобразовать серый в цвета
function image_gray_to_color(r,g,b,a)
    -- прикодим цвета каналов к единому значению
    local fullgray = (r*0.33) + (g*0.33) + (b*0.33);
    r = 0 + fullgray;
    g = 0;
    b = 1 - fullgray;
    return r, g, b, a;
end
-- отрисовать результат
function love.draw()
    if image then
       love.graphics.draw(image,pose.x,pose.y,0,sx+scal,sy+scal);
    end
end

Ненужно, но хуже не будет :D

LINUX-ORG-RU ★★★★★
()
Последнее исправление: LINUX-ORG-RU (всего исправлений: 1)

Надо яркость перевести в цветлвое пространство HSV или HSL, а оттуда уже в RGB. Перевод в HSL/HSV - простое линейное преобразование, можно произвольно масштабировать, складывать и умножать.

Puzan ★★★★★
()
Ответ на: комментарий от LINUX-ORG-RU

Вот ещё на чистой сишке для TGA формата

  • RGBA только 4 канала иначе упадёт
  • NO RLE без RLE сжатия и цветовых таблиц
  • TOP LEFT я запутался маленько с ориентацией, может случится перевёртышь

gcc main.c -o tocolor && ./tocolot input.tga output.tga

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>

struct image
{
    uint16_t size_x;
    uint16_t size_y;
    uint8_t *image;
    uint8_t *image_data;
};

struct color
{
    uint8_t r;
    uint8_t g;
    uint8_t b;
    uint8_t a;
};

enum chanel
{
    R,G,B,A
};

struct image * load_image(const char * filename)
{
    FILE * file = fopen(filename,"r");
    if(!file)
    {
        fprintf(stderr,"Filed open file '%s' %s:%d\n",filename,__FILE__,__LINE__);
        return NULL;
    }

    fseek(file,0,SEEK_END);
    long file_len= ftell(file);
    fseek(file,0,SEEK_SET);

    uint8_t * imagex = malloc(sizeof(uint8_t) * file_len);
    if(!imagex)
    {
        fprintf(stderr,"Filed allocate memm '%s' %s:%d\n",filename,__FILE__,__LINE__);
        fclose(file);
        return NULL;
    }

    size_t read_len = fread(imagex,file_len,1,file);
    if(!read_len)
    {
        fprintf(stderr,"File is empty '%s' %s:%d\n",filename,__FILE__,__LINE__);
        fclose(file);
        free(imagex);
        return NULL;
    }

    uint16_t width, height = 0;
    char footer = 0;
    char header = 18;
    char depth  = 0;
    char descriptor = 0;
    char true_color_type = 0;
    const char true_color_rle = 10;
    const char true_color_no_rle = 2;

    true_color_type = imagex[2];
    width = *(uint16_t*)(imagex+12);
    height= *(uint16_t*)(imagex+14);
    depth = imagex[16];
    descriptor = imagex[17];
    int start_coord = (descriptor  >> 5) & 1u;

    if(true_color_type == true_color_rle )
    {
        fprintf(stderr,"No support RLE compress%s:%d",__FILE__,__LINE__);
        fclose(file);
        free(imagex);
        return NULL;
    }

    struct image * img = malloc(sizeof(struct image));

    if(!img)
    {
        fprintf(stderr,"Filed allocate memm '%s' %s:%d\n",filename,__FILE__,__LINE__);
        fclose(file);
        free(imagex);
        return NULL;
    }

    img->size_x = width;
    img->size_y = height;
    img->image  = imagex;
    img->image_data = imagex+header;
    fclose(file);
    return img;
}

void save_image(struct image * img,const char * filename)
{
   unsigned char y = img->size_y;
   unsigned char xa= img->size_x % 256;
   unsigned char xb= (img->size_x-xa)/256;
   unsigned char ya= img->size_y % 256;
   unsigned char yb= (img->size_y-ya)/256;
   unsigned char header[18] = {0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, xa, xb, ya, yb, 32, 0};
   FILE * file = fopen(filename, "wb");
   fwrite(header,1, sizeof(header), file);
   fwrite(img->image_data,1, img->size_x * img->size_y * 4, file);
}

void map_image(struct image * img, uint8_t (*func)(int x, int y,struct color color, enum chanel))
{
    for (int yy = 0;  yy < img->size_y; ++yy)
    for (int xx = 0;  xx < img->size_x; ++xx)
    {
        struct color c = {
         .r =  img->image_data[xx * 4 + yy * img->size_x * 4 + 0],
         .g =  img->image_data[xx * 4 + yy * img->size_x * 4 + 1],
         .b =  img->image_data[xx * 4 + yy * img->size_x * 4 + 2],
         .a =  img->image_data[xx * 4 + yy * img->size_x * 4 + 3],
        };

        img->image_data[xx * 4 + yy * img->size_x * 4 + 0] = func(xx,yy,c,B);
        img->image_data[xx * 4 + yy * img->size_x * 4 + 1] = func(xx,yy,c,G);
        img->image_data[xx * 4 + yy * img->size_x * 4 + 2] = func(xx,yy,c,R);
        img->image_data[xx * 4 + yy * img->size_x * 4 + 3] = func(xx,yy,c,A);
    }
}


uint8_t gray_to_color(int x, int y ,struct color c,enum chanel ch)
{
    float fullgray = ((float)c.r/255) * 0.33 +
                     ((float)c.g/255) * 0.33 +
                     ((float)c.b/255) * 0.33 ;
    switch(ch)
    {
        case R: return fullgray * 255;
        case G: return 0;
        case B: return 255 - (fullgray) * 255;
        case A: return c.a;
        default: return 0;
    }
    return 0;
}

int main(int argc, char *argv[])
{
   struct image * img = NULL;

   if(argc >= 3)
    {
        img = load_image(argv[1]);
        if(img)
        {
            map_image(img,gray_to_color);
            save_image(img,argv[2]);
        }else{
            printf("Ошибка открытия файла\n");
        }
    }else{
          printf("программа входящая_картинка.tga сохраняемая_картинка.tga\n");
    }

    return 0;
}
LINUX-ORG-RU ★★★★★
()

от синего к красному

Яркости синего и красного контрастируют меньше, чем яркости чёрного и белого. Чтобы в этом убедиться, достаточно такую «сине-красную» картинку перевести обратно в ЧБ: convert br.png -colorspace gray bw.png.

Если хотите упростить, а не усложнить восприятие исходной ЧБ картинки, то нужно выбирать контрастную цветную гамму, например чёрный-синий-красный-жёлтый-белый. Из SO-ссылки выше хорошие цветовые карты - COLORMAP_OCEAN и COLORMAP_HOT.

anonymous
()

Я делал такое. Вкратце - берешь палитру, с цветами по точкам от 0 до 1. Есть разные - погугли «FLIR palette».

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

Библиотеки для этого это смешное, это только в жопоскрипте делают всякие leftpad. OpenCV и прочий трешак это явный оверкилл.

lovesan ★★
()

Это настолько простая задача, что даже не понимаю, как может возникнуть проблема в её реализации. Единственный вопрос, это правильный подбор палитры при конвертации GreyScale в RGB. Какой диапазон температур представлен на входе и его разрешение(4,8,16 и т.д. бит), какой диапазон температур хочется выделить на результирующем изображении.

Реализация же самого алгоритма это уровень 1 курса универа или последние классы спецшколы по информатики.

WatchCat ★★★★★
()
Ответ на: комментарий от HE_KOT

https://i.postimg.cc/zGWYd1j9/01.jpg

Патч к коду Gray > Red/Blue (тепловизор) (комментарий)


+uint8_t green_value (float gray) {
+
+	if ( (gray * 255) < 128) return (255 - (gray) * 255 );
+	else return (gray * 255);
+}

uint8_t gray_to_color(int x, int y ,struct color c,enum chanel ch)
{
    float fullgray = ((float)c.r/255) * 0.33 +
                     ((float)c.g/255) * 0.33 +
                     ((float)c.b/255) * 0.33 ;
    switch(ch)
    {
        case R: return fullgray * 255;
-        case G: return 0;
+        case G: return green_value(fullgray);

        case B: return 255 - (fullgray) * 255;
        case A: return c.a;
        default: return 0;
    }
    return 0;
}
anonymous
()
Ответ на: комментарий от lovesan

На какой хер?

Потому что параметра «цвет» в цветовой модели RGB нет. А именно в цвет нужно преобразовать значение температуры. Можно сделать палитру с интерполяцией, но опять цвета в таблице лучше сделать в HSV, т.к. в этой модели инерполяция делается правильно и легко.

Бред собачий.

А ты иди нахер.

Puzan ★★★★★
()
Ответ на: комментарий от anonymous

res.png: https://0x0.st/HEE9.png

Все равно что-то не то. Как-то потерялось ощущение, что это инфракрасная картинка. Рыжий мальчишка с красными ушами, в темноте, в красной майке и со светящимся лицом….

anonymous
()
Ответ на: комментарий от Puzan

У него от тепловизора идет карта температур, на выходе ему нужно RGB, на какой хер ему перегонять в HSV? Каким образом интерполяция точки между двумя векторами в трехмерном векторе в HSV лучше чем в RGB? Ты грибов объелся.

lovesan ★★
()
Ответ на: комментарий от lovesan

Ты грибов объелся.

Проспись. А как отпустит, подумай ещё раз, как ты будешь интерполировать между, например, ярким синим и тёмным красным в RGB. Не неси херни, не позорься.

А лучше сделай оба варианта, сравни, и покайся.

Puzan ★★★★★
()
Последнее исправление: Puzan (всего исправлений: 1)