#๐Ÿ”’ Code for color adjustment of an image does not work

135 messages ยท Page 1 of 1 (latest)

civic bladeBOT
#

@languid kestrel

Python help channel opened

Remember to:

  • Ask your Python question, not if you can ask or if there's an expert who can help.
  • Show a code sample as text (rather than a screenshot) and the error message, if you've got one.
  • Explain what you expect to happen and what actually happens.

:warning: Do not pip install anything that isn't related to your question, especially if asked to over DMs.

dry kettle
#

what do you mean

languid kestrel
#

Was my explanation not saved?

#

Hi, I have the following problem with the attached code: Starting from an Excel list of 81 colors, an image is to be color-matched so that the image only consists of these colors. To do this, a decision must be made for each pixel as to whether its color is part of the 81 colors. If not, the next closest color must be selected.

The problem with the code is that the adjusted image partly consists of colors that are not part of the 81 colors.

I hope you understand what I mean and someone has a solution for the problem.

Thanks in advance!
Max

vague hill
#

Maybe youโ€™ve uploaded a text file or .py file of sorts?
It gets auto deleted by the bot.

civic bladeBOT
#

Hey @languid kestrel!

It looks like you're trying to paste code into this channel.

Discord has support for Markdown, which allows you to post code with full syntax highlighting. Please use these whenever you paste code, as this helps improve the legibility and makes it easier for us to help you.

To do this, use the following method:
```py
print('Hello, world!')
```

This will result in the following:

print('Hello, world!')```
You can **edit your original message** to correct your code block.
late finch
#
from PIL import Image
import numpy as np
from collections import Counter
import openpyxl
from math import sqrt

# Function to read cells from an Excel file
def read_excel_cells(file_path, sheet_name, start_cell, end_cell):
    workbook = openpyxl.load_workbook(file_path)
    sheet = workbook[sheet_name]
    values = []

    for row in sheet[start_cell:end_cell]:
        for cell in row:
            values.append(cell.value)

    return values

# Function to find the closest color
def closest_color(rgb):
    r, g, b = rgb
    color_diffs = []
    for color in colors_rgb:
        cr, cg, cb = color
        color_diff = sqrt((r - cr)**2 + (g - cg)**2 + (b - cb)**2)
        color_diffs.append((color_diff, color))
    return min(color_diffs)[1]

# Load colors from the Excel file
file_path = r'C:\Users\maxik\Desktop\Mosaik\Mosaik.xlsx'
sheet_name = 'Farben'
start_cell = 'A2'
end_cell = 'A82'
colors_hex = read_excel_cells(file_path, sheet_name, start_cell, end_cell)

# Convert HEX colors to RGB
colors_rgb = [tuple(int(hex[i:i + 2], 16) for i in (1, 3, 5)) for hex in colors_hex]

# Load the image
image = Image.open(r"C:\Users\maxik\Desktop\Mosaik\Celebreties\Billie_Eilish\Billie_Eilish_cropped.jpg")

# Convert image to a numpy array to manipulate pixels
image_array = np.array(image)

# Color adjustment for each pixel in the image
for i in range(image_array.shape[0]):
    for j in range(image_array.shape[1]):
        pixel = image_array[i, j]
        new_color = closest_color(pixel)
        image_array[i, j] = new_color

# Save the modified image
modified_image = Image.fromarray(image_array)
modified_image.save(r"C:\Users\maxik\Desktop\Mosaik\Celebreties\Billie_Eilish\Billie_Eilish_vereinfacht.jpg")
print("success")
languid kestrel
#

Is the problem a little clearer now?

late finch
#

what does your input image look like

#

and your excel file

#

i would probably do a

print( colors_rgb )

To see if its converting properly

languid kestrel
#

This is the original image and the adjusted one.

late finch
#

cool

#

ok so

#

The problem with the code is that the adjusted image partly consists of colors that are not part of the 81 colors.

#

this is what you said earlier

languid kestrel
#

yeah

late finch
#

do any of the colors actually match?

languid kestrel
#

Yes, a great many of them.

late finch
#

ok but some do not?

languid kestrel
#

oh wait

late finch
#

?

languid kestrel
#

These are the predefined colors.

late finch
#

yes thats what i assumed haha

#

ok so first thing i would change is to save as a png instead of jpg

#

idk if it matters

#

but that way you'll preserve more info

#

idk if it compresses your output if it goes for jpg

languid kestrel
#

Okay, got it!

late finch
#

did that work?

#

let me know if it works

languid kestrel
#

The code is currently running... it always takes a while

late finch
#

kk

#

i wonder if we could make it faster

#

i dont know much about multi-processing

#

but it could cut the time down

languid kestrel
#

I mean... the code has to look at every single pixel and calculate and compare the distances to the 81 colors... I'm not surprised that it takes so long ๐Ÿ˜…

late finch
#

can you send me the excel file as well?

#

let me try somthing on my end

languid kestrel
#

This color, for example, should not actually occur: #535353

late finch
#

gotcha

languid kestrel
late finch
#

yeah send me your excel file

#

i'll try to run it localy

languid kestrel
#

The colors are in the sheet "Colors"

#

"Farben"

late finch
#

thats fine, i just need the file to run locally lol

#

did you send the file?

#

ah ok just received thank you

#

well it looks like you're using numpy

#

so maybe we can make this faster

#

but i guess first we gotta figure out the color issue huh?

languid kestrel
#

yeah

late finch
#

wait

#

so your closest color function

#

it calculates the color difference

#

what does min() do?

#

only return the color itself?

languid kestrel
#

The color with the smallest difference or distance should be output.

late finch
#

should lol

#

yeah lets double check

languid kestrel
#

To be honest, I solved this part of the code with ChatGPT ๐Ÿ˜…

late finch
#

๐Ÿ˜…

#

thats fine, just that you should understand what the code is doing

#

these AIs can be wrong or miss things too

languid kestrel
#

yeah sure

late finch
#

what you have so far is close though!

#

so here's what we'll do

#

first thing i restructured your code a little bit

#
from PIL import Image
import numpy as np
from collections import Counter
import openpyxl
from math import sqrt


# Function to read cells from an Excel file
def read_excel_cells(file_path, sheet_name, start_cell, end_cell):
    workbook = openpyxl.load_workbook(file_path)
    sheet = workbook[sheet_name]
    values = []

    for row in sheet[start_cell:end_cell]:
        for cell in row:
            values.append(cell.value)

    return values


# Function to find the closest color
def closest_color(rgb, colors_rgb):
    r, g, b = rgb
    color_diffs = []
    for color in colors_rgb:
        cr, cg, cb = color
        color_diff = sqrt((r - cr) ** 2 + (g - cg) ** 2 + (b - cb) ** 2)
        color_diffs.append((color_diff, color))
    return min(color_diffs)[1]


def convert_image():
    # Load colors from the Excel file
    excel_file_path = r"./Mosaik.xlsx"
    sheet_name = "Farben"
    start_cell = "A2"
    end_cell = "A82"
    colors_hex = read_excel_cells(excel_file_path, sheet_name, start_cell, end_cell)

    # Convert HEX colors to RGB
    colors_rgb = [
        tuple(int(hex[i : i + 2], 16) for i in (1, 3, 5)) for hex in colors_hex
    ]

    # Load the image
    input_image = Image.open(r"./Billie_Eilish_cropped_min.jpg")

    # Convert image to a numpy array to manipulate pixels
    image_array = np.array(input_image)

    # Color adjustment for each pixel in the image
    for i in range(image_array.shape[0]):
        for j in range(image_array.shape[1]):
            pixel = image_array[i, j]
            new_color = closest_color(pixel, colors_rgb)
            image_array[i, j] = new_color

    # Save the modified image
    modified_image = Image.fromarray(image_array)
    modified_image.save(r"./Billie_Eilish_vereinfacht.jpg")
    print("success")


if __name__ == "__main__":
    convert_image()

#

next lets set up a small unittest

languid kestrel
late finch
#

sure

#

so if you noticed, instead of it being a functional script

#

i moved the logic into convert_image() as a function

#

just keeps things cleaner

#

next, i scaled this down to 100x150

#

so that it doesnt take a long time to run

languid kestrel
#

ah got it!

late finch
#

but first we need to see if closest_color is running properly

#

so i added

#
import unittest
#

to the top

#

and

#
class TestConvert(unittest.TestCase):
    pass
#

above main

languid kestrel
#

got it!

late finch
#

so now uh

#

lets start with your first color

#

which in rgb is

#

76, 16, 14

#
class TestConvert(unittest.TestCase):
    def test_known_color(self):
        colors_rgb = get_colors_from_excel()
        result = closest_color((76, 16, 14), colors_rgb)

        self.assertEqual(result, (76, 16, 14))
#

and this test passes

#

but what if we change the rgb values a little bit

#

looks to be working if we just change the B value

languid kestrel
#

Interesting!

late finch
#

well it seems to be working

#

let me convert these rgbs to hex

languid kestrel
#

Great!

late finch
#
class TestConvert(unittest.TestCase):
    def test_known_color(self):
        colors_rgb = get_colors_from_excel()
        result = closest_color((76, 16, 14), colors_rgb)

        self.assertEqual(result, (76, 16, 14))

    def test_known_color_modified(self):
        colors_rgb = get_colors_from_excel()

        for i in range(255):
            result = closest_color((76, 16, i), colors_rgb)

            print(result)
            # self.assertEqual(result, (76, 16, 14))

#

ok so now we're gonna try something different

#

get away from the testing

#

and just run all the colors through this lol

#

one sec

languid kestrel
#

yeah

#

sounds great

#

If I can help you in any way, please let me know ๐Ÿ™‚

late finch
#

i dont even know myself ๐Ÿ˜‚

#

figuring it out as i go

#

ok lets see

#

this is the current state of the test lol

#

ok

#

looks like the function is working properly with all the colors

#

so then it comes down to probably how its being saved

#

so lets test that next

#

we'll have to open the modified file and compare all the colors there now lol

languid kestrel
#

Okay! ๐Ÿ˜…

#

If it's okay with you, I'll get back to you in a few hours... it's already late here (Germany)

late finch
#

yeah i'll post any updates here for you to look at in the morning

#

just testing the output now

languid kestrel
#

Thanks for your help so far!

late finch
#
PS C:\Users\Bilal\python discord\maxi> & "c:/Users/Bilal/python discord/.venv/Scripts/python.exe" "c:/Users/Bilal/python discord/maxi/main.py"
unique_to_colors_hex= {'#ffffff'}
unique_to_results= {'#e6b942', '#16586f', '#969a9f', '#317738', '#a01518', '#61a44e', '#a8b7c9', '#064a69', '#1b3653', '#b03280', '#3c9abc', '#915f1c', '#591865', '#071127', '#aec97b', '#c64180', '#afd0cd', '#405e2c',
'#d3942c', '#7f922f', '#FFFFFF', '#6a4d8f', '#7c294e', '#877dba', '#b3a3c1', '#c33c1b', '#528292', '#1c2317', '#0a6e7a', '#7d124f', '#4f736c', '#03419f', '#b07fa4', '#323718', '#556880', '#195835', '#6d90c7', '#5d5e3b',       
'#190855', '#484c52', '#bac75c', '#850b0c', '#ea5056', '#2074bc', '#64a2ca', '#15191f', '#334553', '#021d64', '#e4cf72', '#161616', '#e7652f', '#24261a', '#3376bb', '#4a74a7', '#98af9e'}
#

yeah thats a lot of new colors

#

my guess is its just the way that PIL generates an image ๐Ÿคท

#

i dont know if you can make it stricter

#

ok

#

the program seems to be fine according to my test ๐Ÿคท

#

no mismatched colors

inner spoke
civic bladeBOT
#
Python help channel closed

This help channel has been closed and it's no longer possible to send messages here. If your question wasn't answered, feel free to create a new post in #1035199133436354600. To maximize your chances of getting a response, check out this guide on asking good questions.