Home > Net >  Why my photo collage output using numpy has strange color profile?
Why my photo collage output using numpy has strange color profile?

Time:04-13

After a long time of researching and asking questions, I have made my prototype code that makes a collage of a list of photos given as a list of strs.

It resizes the images according to the positions of the images in the list, then randomly rotates the images and randomly arrange them in a minimum bounding area.

It uses cv2, numpy, PIL and rpack, to be honest I have absolutely no idea how these libraries work, why my code is working, I just know how to make them work, I only know how to put them together.

So here is my code:

import cv2
import numpy as np
import random
import rpack
from fractions import Fraction
from math import prod
from pathlib import Path
from PIL import Image
from typing import Tuple

folder = 'D:/test/'

images = [
    'Mass Effect.jpg',
    'Dragon Age Origins.jpg',
    'Life Is Strange.jpg',
    'Star Wars KOTOR.jpg',
    'Dragon Age 2.jpg',
    'Choice of Robots.jpg',  
    'Perfect Match.png',
    'Jade Empire.jpg',
    "Serafina's Saga.jpg",
    'Rising Angels Reborn.jpg',       
    'Across The Void.png',
    "Heart's Blight.png", 
    'The Gray Wolf And The Little Lamb.jpg',
    'Night of the Lesbian Vampires.png',                 
    'Tethered.png',
    'Contract Demon.jpg',
    "Yuki's 4P.png"
]                        

def resize_guide(image_size: Tuple[int, int], unit_shape: Tuple[int, int], target_ratio: float) -> Tuple[int, int]:
    aspect_ratio = Fraction(*image_size).limit_denominator()
    horizontal = aspect_ratio.numerator
    vertical = aspect_ratio.denominator
    target_area = prod(unit_shape) * target_ratio
    unit_length = (target_area/(horizontal*vertical))**.5
    return (int(horizontal*unit_length), int(vertical*unit_length))

images = [cv2.imread(folder name) for name in images]
size_hint = [i**.75 for i in range(1, len(images) 1)][::-1]
resized_images = []

for image, hint in zip(images, size_hint):
    height, width = image.shape[:2]
    guide = resize_guide((width, height), (640,360), hint)
    resized = cv2.resize(image, guide, interpolation = cv2.INTER_AREA)
    resized_images.append(resized)

def make_border(image, value, border=16):
    return cv2.copyMakeBorder(
        image,
        top=border,
        bottom=border,
        left=border,
        right=border,
        borderType=cv2.BORDER_CONSTANT,
        value=value
    )

def rotate_image(image, angle):
    h, w = image.shape[:2]
    cX, cY = (w // 2, h // 2)
    M = cv2.getRotationMatrix2D((cX, cY), -angle, 1.0)
    cos = np.abs(M[0, 0])
    sin = np.abs(M[0, 1])
    nW = int((h * sin)   (w * cos))
    nH = int((h * cos)   (w * sin))
    M[0, 2]  = (nW / 2) - cX
    M[1, 2]  = (nH / 2) - cY
    return cv2.warpAffine(image, M, (nW, nH))

rotated_images = []
sizes = []

for image in resized_images:
    image = make_border(image, (255, 255, 255))
    rotated = rotate_image(image, random.randrange(-15, 16))
    image = make_border(image, (0,0,0))
    rotated_images.append(rotated)
    height, width = rotated.shape[:2]
    sizes.append((width, height))

shapes = [(x, y, w, h) for (x, y), (w, h) in zip(rpack.pack(sizes), sizes)]

rightmost = sorted(shapes, key=lambda x: -x[0] - x[2])[0]
bound_width = rightmost[0]   rightmost[2]

downmost = sorted(shapes, key=lambda x: -x[1] - x[3])[0]
bound_height = downmost[1]   downmost[3]

collage = np.zeros([bound_height, bound_width, 3],dtype=np.uint8)

for image, (x, y, w, h) in zip(rotated_images, shapes):
    collage[y:y h, x:x w] = image

collage = Image.fromarray(collage, 'RGB')

collage.save('D:/collages/'   random.randbytes(4).hex()   '.png')

Because the output is way too large (over 20 MiB) it can't fit here, I have uploaded it to Google Drive: https://drive.google.com/file/d/16w4wsC_od4dh4QI7BYj8MM2gMngbSLV1/view?usp=sharing

So far the results seem promising, the only complaint I have is that the colors look very strange, I swear the original images have normal colors.

Can someone please tell me what I did wrong?


OK so while executing the code, the interpreter complained a lot about:

libpng warning: iCCP: known incorrect sRGB profile

I used cracked Adobe Photoshop CS6 to edit the images, is this the source of the problem or is it something else?

CodePudding user response:

You are doing everything just fine. The only mistake you are making is while storing the image. Just remove the last two lines and add the following line.

cv2.imwrite('D:/collages/'   random.randbytes(4).hex()   '.png', collage)
  • Related