gimp python – как изменить цвет пикселя?

Я хотел бы загрузить 2 изображения jpg с помощью Gimp Python. Затем картинки следует сравнить попиксельно. Если пиксель на картинке 2 имеет определенное значение rgb, пиксель на картинке 1 должен быть окрашен. Перед этим должен быть сделан пользовательский ввод, в который можно ввести начальное значение.

Я не уверен, что gimp python может все это сделать?

В первую очередь я ищу команды:
- Загрузить изображение
- Пользовательский ввод
- Загрузить значение RGB для пикселя
- Изменить значение RGB для пикселя
- Сохранить изображение

Спасибо заранее

Я сначала пробовал c++, но с картинками не так просто. Мой учитель посоветовал мне гимпировать. Схематично это должно выглядеть так:

#include <iostream>
using namespace std;

int main()
{
unsigned long long int startPixelBreite;
unsigned long long int startPixelHoehe;
int prozent;


//EDIT: Load pic 1
//EDIT: load pic 2


//startpixel bestimmen durch usereingabe
    cout << "Startpixel Höhe" << endl;
    cin >> startPixelBreite;
    cout << "Startpixel Höhe" << endl;
    cin >> startPixelHoehe;

//breite + Höhe von bild 1 auslesen
        endpixelBreite = startPixelBreite + bildBreite1
        endpixelHoehe = startPixelHoehe + bildHoehe1

    //ANFANG: Schleife für pixelzeile
        aktuellerPixelX = 0;
        //ANFANG schleife für pixel pixelreihe


             //pixelfarbebild1 einlesen
                /*
                pixelfarbebild1[0]  = //rot
                pixelfarbebild1[1]  = //grün
                pixelfarbebild1[2]  = //blau
                */

            //pixelfarbebild2 einlesen
                /*
                pixelfarbebild2[0]  = //rot
                pixelfarbebild2[1]  = //grün
                pixelfarbebild2[2]  = //blau
                */

            if (aktuellerPixelX > startPixelBreite & aktuellerPixelX< endpixelBreite)
            {
                if pixelfarbe[0] = 102 & pixelfarbe[1] = 102 & pixelfabre [2] = 102 //grau
                {
                    prozent = 60
                    neuerpixel[0] = (pixelfarbebild1[0]*prozent-100*pixelfarbebild1[0]+100*pixelfarbebild2[0])/prozent  //rot
                    neuerpixel[1] = (pixelfarbebild1[1]*prozent-100*pixelfarbebild1[1]+100*pixelfarbebild2[1])/prozent  //grün
                    neuerpixel[2] = (pixelfarbebild1[2]*prozent-100*pixelfarbebild1[2]+100*pixelfarbebild2[2])/prozent  //blau
                }
                else if pixelfarbe[0] = 237 & pixelfarbe[1] = 136 & pixelfabre [2] = 196 //pink
                {
                    prozent = 70
                    neuerpixel[0] = (pixelfarbebild1[0]*prozent-100*pixelfarbebild1[0]+100*pixelfarbebild2[0])/prozent  //rot
                    neuerpixel[1] = (pixelfarbebild1[1]*prozent-100*pixelfarbebild1[1]+100*pixelfarbebild2[1])/prozent  //grün
                    neuerpixel[2] = (pixelfarbebild1[2]*prozent-100*pixelfarbebild1[2]+100*pixelfarbebild2[2])/prozent  //blau
                }
                else if pixelfarbe[0] = 175 & pixelfarbe[1] = 167 & pixelfabre [2] = 172 //hellgrau
                {
                    prozent = 67
                    neuerpixel[0] = (pixelfarbebild1[0]*prozent-100*pixelfarbebild1[0]+100*pixelfarbebild2[0])/prozent  //rot
                    neuerpixel[1] = (pixelfarbebild1[1]*prozent-100*pixelfarbebild1[1]+100*pixelfarbebild2[1])/prozent  //grün
                    neuerpixel[2] = (pixelfarbebild1[2]*prozent-100*pixelfarbebild1[2]+100*pixelfarbebild2[2])/prozent  //blau
                }
                else
                {
                    neuerpixel[0] = pixelfarbebild2[0]  //rot
                    neuerpixel[1] = pixelfarbebild2[1]  //grün
                    neuerpixel[2] = pixelfarbebild2[2]  //blau
                }

                //pixel in bild schreiben
            }
            else{
                neuerpixel[0] = pixelfarbebild2[0]  //rot
                neuerpixel[1] = pixelfarbebild2[1]  //grün
                neuerpixel[2] = pixelfarbebild2[2]  //blau
            }

            aktuellerPixelX++;

        //ENDE schleife für pixel pixelreihe

    //ENDE: Schleife für pixelzeile
//ausgabe

}

person Chris    schedule 19.11.2018    source источник
comment
Пожалуйста, покажите код того, что вы пробовали до сих пор.   -  person mbuechmann    schedule 19.11.2018
comment
Дополнение смотрите выше   -  person Chris    schedule 19.11.2018
comment
Что вы пробовали в питоне?   -  person mbuechmann    schedule 19.11.2018
comment
Если вы просто пытаетесь массово обрабатывать изображения, вы можете (должны...) избегать Gimp. Существуют библиотеки Python для загрузки/сохранения и редактирования изображений, см. PIL (или его подушку). ImageMagick также имеет привязки для Python.   -  person xenoid    schedule 20.11.2018


Ответы (4)


Вы можете/должны использовать «пиксельные области» для экспорта/импорта слоев в/из массивов python. Мой скрипт использует это для передачи пикселей Gimp в массив numpy:

# Returns NP array (N,bpp) (single vector of triplets)
def channelData(layer):
    w,h=layer.width,layer.height
    region=layer.get_pixel_rgn(0, 0, w,h)
    pixChars=region[:,:]
    bpp=region.bpp
    return np.frombuffer(pixChars,dtype=np.uint8).reshape(w,h,bpp)

Это код Gimp 2.8, возможно, потребуются некоторые изменения для поддержки более высокой разрядности в 2.10.

В обратном направлении:

def createResultLayer(image,name,result):
    rlBytes=np.uint8(result).tobytes();
    rl=gimp.Layer(image,name,image.width,image.height,
                  image.active_layer.type,100,NORMAL_MODE)
    region=rl.get_pixel_rgn(0, 0, rl.width,rl.height,True)
    region[:,:]=rlBytes
    image.add_layer(rl,0)
    gimp.displays_flush()

Вы, конечно, можете отказаться от пустой части, но если вы можете выразить свою проблему как операции с глобальным массивом, все может быть очень быстро. В Windows (или при использовании версии flatpak в Linux) вам необходимо добавить numpy в среду выполнения Python, используемую Gimp. См. здесь некоторые подсказки. Здесь вы найдете полный скрипт, который также можно использовать в качестве примера того, как получить изображение и слой.

См. здесь документацию по API для Python.

person xenoid    schedule 19.11.2018
comment
спасибо за пример. Можете ли вы отредактировать пример, чтобы показать, как написать один пиксель? Документы на самом деле не показывают, как выглядит формат пикселя. В API указано: Тип индекса — это строка, содержащая двоичные данные запрошенного региона. - person Rumble; 03.10.2019

В GIMP проверьте процедуры gimp_drawable_get_pixel и gimp_drawable_set_pixel. Вы можете найти все процедуры, которые вы можете использовать в плагине Python, в Фильтры -> Python Fu -> Консоль.

Очень простой код, просто чтобы дать вам представление, может быть:

color_to_edit = (102, 102, 102) #or whatever color you wish to edit, this is an RGB value without alpha channel
new_color = (200, 200, 200) #the new color
for i in range(x_size):
    for j in range(y_size):
        num_channels, pixel = pdb.gimp_drawable_get_pixel(drawable, i, j)
        if all([p == q for p, q in zip(pixel, color_to_edit)]):
            pdb.gimp_drawable_set_pixel(drawable, i, j, 3, new_color)
pdb.gimp_displays_flush() #this will update the image.

Здесь drawable должен быть слой GIMP с вашим изображением.

person Valentino    schedule 19.11.2018
comment
get_pixel() и set_pixel() — очень медленные операции. Они подходят для пробы цвета, но не подходят для полного изображения. - person xenoid; 20.11.2018
comment
@xenoid приятно упомянуть об этом. Так как же правильно к этому подступиться? - person Rumble; 03.10.2019
comment
Смотрите мой собственный ответ о пиксельных областях и, возможно, об использовании numpy. - person xenoid; 03.10.2019

Совершенно другой ответ, который позволяет избежать извлечения пикселей из Gimp.

Итак, у нас есть слой «изображение» (где вы окрашиваете пиксели) и слой «карта» (где заданный цвет указывает, какие пиксели должны быть окрашены). Затем:

  • Сделайте выбор цвета на слое «карта» (gimp_by_color_select(maplayer,...))
  • Используя этот выбор (который является глобальным на изображении и поэтому применим к любому слою), раскрасьте пиксели на слое изображения (выделение с заливкой ведро, для однородного цвета: gimp_edit_bucket_fill(imagelayer,...)).
  • Для более сложных цветовых схем вы можете нарисовать 3-й слой, вставить его под слой «изображение» и удалить выбранные пиксели, чтобы сделать его видимым, а затем объединить слой изображения с ним.

Все это делается с помощью операторов Gimp и очень быстро. Его также можно использовать как ручную процедуру, поэтому вы можете сначала попробовать его в Gimp, не написав ни одной строки кода.

person xenoid    schedule 19.11.2018

В матлабе/октаве это очень просто. Нет необходимости в gimp и хорошо интегрируется с C++, если вам абсолютно необходимо иметь интеграцию с кодом C++. Например, предположим, что вы хотите изменить пиксели Image2 на R: 50, G: 60, B: 70, всякий раз, когда Image1 имеет пиксели R: 10, G: 20, B: 30. Затем:

% Alle kommentierure im lingula obfuscatis fur demonstraru how rude it looks

Im1 = imread('im1.jpg');  Im2 = imread('im2.jpg'); % readure imagurine
 R1 = Im1(:,:,1);          R2 = Im2(:,:,1);        % selectu 'red'   layeru piripitsi
 G1 = Im1(:,:,2);          G2 = Im2(:,:,2);        % selectu 'green' layeru piripitsi
 B1 = Im1(:,:,3);          B2 = Im2(:,:,3);        % selectu 'blue'  layeru piripitsi

Mask = (R1 == 10) & (G1 == 20) & (B1 == 30); % криеит маск фром чаннелз
R2(Mask) = 50; % πουτ 50 γουεαρ Mask ηζ True!
G2(Mask) = 60; % πουτ 60 γουεαρ Mask ηζ True!
B2(Mask) = 70; % πουτ 70 γουεαρ Mask ηζ True!

NewIm2 = cat(3, R2, G2, B2); % Sukasumeseleba! Habibi chan! Uleleleleleeeeeeeh!!!!!

Вы можете читать и сравнивать изображения аналогичным образом в python, используя scipy.imread, numpy и т. д., если вы предпочитаете python вместо matlab. Гимп не нужен.


ПС. Как вы, возможно, поняли из моих саркастических комментариев к коду, рассмотрите возможность написания кода исключительно на английском языке, когда обращаетесь к международной аудитории, такой как SO. Очень неприятно и утомительно читать такой «смешанный» код, и поэтому он выглядит грубым и невнимательным; (и это верно даже для кого-то вроде меня лично, несмотря на то, что я неплохо говорю по-немецки, а английский не является моим родным языком). Не говоря уже о том, что вы рискуете напрасно ограничить свою аудиторию только говорящими по-немецки!

person Tasos Papastylianou    schedule 20.11.2018