पायथन में पीआईएल या ओपनसीवी का उपयोग करके बदल दी गई क्षमता के साथ दो दिए गए समन्वय पर एक छवि को दूसरी छवि में पेस्ट करें

Dec 10 2020

मेरे पास दिए गए बिंदुओं के साथ दो छवियां हैं, प्रत्येक बिंदु एक छवि है, जिसे संरेखित करने की आवश्यकता है ताकि परिणाम छवि दोनों छवियों का एक योग हो, जबकि छवि 2 को छवि 1 पर 40% अस्पष्टता के साथ चिपकाया जाता है। मैंने इस सवाल को ध्यान में रखा है, लेकिन हमारा मामला बिल्कुल मेल नहीं खाता क्योंकि छवि को-ऑर्डिनेट उपयोगकर्ता द्वारा आपूर्ति की जाती है और छवियों का आकार कई प्रकार का हो सकता है।

चित्र 1:

चित्र 2:

अंतिम परिणाम (वांछित आउटपुट):

इसके लिए मैंने img.paste()PIL के कार्य को आजमाया है और cv2 में छवियों के संख्यात्मक सरणी में मानों को प्रतिस्थापित किया है, दोनों ऐसे परिणाम दे रहे हैं जो वांछित से दूर हैं।

जवाब

1 MarkSetchell Dec 11 2020 at 19:07

मैंने इस तरह ImageMagick के साथ दो इनपुट चित्र बनाए :

magick -size 300x400 xc:"rgb(1,204,255)" -fill red -draw "point 280,250" 1.png
magick -size 250x80  xc:"rgb(150,203,0)" -fill red -draw "point 12,25"   2.png

फिर निम्न कोड भागा:

#!/usr/bin/env python3
"""
Paste one image on top of another such that given points in each are coincident.
"""

from PIL import Image

# Open images and ensure RGB
im1 = Image.open('1.png').convert('RGB')
im2 = Image.open('2.png').convert('RGB')

# x,y coordinates of point in each image
p1x, p1y = 280, 250
p2x, p2y = 12, 25

# Work out how many pixels of space we need left, right, above, below common point in new image
pL = max(p1x, p2x)
pR = max(im1.width-p1x,  im2.width-p2x)
pT = max(p1y, p2y)
pB = max(im1.height-p1y, im2.height-p2y)

# Create background in solid white
bg = Image.new('RGB', (pL+pR, pT+pB),'white')
bg.save('DEBUG-bg.png')

# Paste im1 onto background
bg.paste(im1, (pL-p1x, pT-p1y))
bg.save('DEBUG-bg+im1.png')

# Make 40% opacity mask for im2
alpha = Image.new('L', (im2.width,im2.height), int(40*255/100))
alpha.save('DEBUG-alpha.png')

# Paste im2 over background with alpha
bg.paste(im2, (pL-p2x, pT-p2y), alpha)
bg.save('result.png')

परिणाम यह है:

शुरू करने वाले नामों के साथ छवियां सहेजने वाली रेखाएं "DEBUG-xxx.png"केवल आसान डिबगिंग के लिए हैं और उन्हें हटाया जा सकता है। मैं उन सभी को आसानी से देख सकता हूं कि कोड के साथ क्या चल रहा है और मैं आसानी से हटाकर उन सभी को हटा सकता हूं "DEBUG*png"

Thymen Dec 11 2020 at 05:04

किसी भी अधिक विवरण के बिना, मैं इस प्रश्न का उत्तर सबसे अच्छा देने की कोशिश करूंगा जितना कि मैं कर सकता हूं और उन सभी अतिरिक्त मान्यताओं को नाम दूंगा जो मैंने किए (और यदि आप उन्हें नहीं बना सकते हैं तो उन्हें कैसे संभालें)।

चूंकि कोई प्रदान की गई छवियां नहीं थीं, इसलिए मैंने निम्न कोड का उपयोग करते हुए विलय के रूप में एक काले बिंदु के साथ एक नीली और हरी छवि बनाई:

import numpy as np

from PIL import Image, ImageDraw


def create_image_with_point(name, color, x, y, width=3):
    image = np.full((400, 400, 3), color, dtype=np.uint8)
    image[y - width:y + width, x - width:x + width] = (0, 0, 0)
    image = Image.fromarray(image, mode='RGB')
    ImageDraw.Draw(image).text((x - 15, y - 20), 'Point', (0, 0, 0))
    image.save(name)
    return image


blue = create_image_with_point('blue.png', color=(50, 50, 255), x=300, y=100)
green = create_image_with_point('green.png', color=(50, 255, 50), x=50, y=50)

यह निम्नलिखित छवियों में परिणाम है:

अब मैं यह धारणा बनाऊंगा कि छवियों में अभी तक एक अल्फा परत नहीं है (जैसा कि मैंने उन्हें बिना बनाया है)। इसलिए मैं छवि को लोड करूंगा और उनमें एक अल्फा लेयर जोड़ूंगा:

import numpy as np

from PIL import Image

blue = Image.open('blue.png')
blue.putalpha(255)

green = Image.open('green.png')
green.putalpha(255)

मेरी निम्नलिखित धारणा यह है कि आप पहले से मर्ज निर्देशांक जानते हैं:

# Assuming x, y coordinates.
point_blue = (300, 100)
point_green = (50, 50)

फिर आप एक खाली छवि बना सकते हैं, जो दोनों छवियों को आसानी से पकड़ सकता है:

new_image = np.zeros((1000, 1000, 4), dtype=np.uint8)

यदि आप पहले से छवि आकार नहीं जानते हैं, तो यह एक दूर की धारणा है, और यदि आप यह नहीं जानते हैं तो आपको दो छवियों के संयोजन आकार की गणना करनी होगी।

फिर आप छवियों को नए बनाए गए चित्रों के केंद्र में रख सकते हैं (मेरे मामले में (500, 500)। इसके लिए आप ऑफ़सेट के रूप में विलय के बिंदुओं का उपयोग करते हैं। और आप विलय करने के लिए अल्फा सम्मिश्रण (किसी भी स्थिति में np.uint8(img_1*alpha + img_2*(1-alpha))) कर सकते हैं। विभिन्न अपारदर्शिता का उपयोग करते हुए चित्र।

जो कोड में है:

def place_image(image: Image, point_xy: tuple[int, int], dest: np.ndarray, alpha: float = 1.) -> np.ndarray:

    # Place the merging dot on (500, 500).
    offset_x, offset_y = 500 - point_xy[0], 500 - point_xy[1]

    # Calculate the location of the image and perform alpha blending.
    destination = dest[offset_y:offset_y + image.height, offset_x:offset_x + image.width]
    destination = np.uint8(destination * (1 - alpha) + np.array(image) * alpha)

    # Copy the 'merged' imaged to the destination location.
    dest[offset_y:offset_y + image.height, offset_x:offset_x + image.width] = destination
    return dest

# Add the background image blue with alpha 1
new_image = place_image(blue, point_blue, dest=new_image, alpha=1)

# Add the second image with 40% opacity
new_image = place_image(green, point_green, dest=new_image, alpha=0.4)

# Store the resulting image.
image = Image.fromarray(new_image)
image.save('result.png')

अंतिम परिणाम एक बड़ी छवि होगी, संयुक्त चित्रों की, फिर से आप सही बाउंडिंग बॉक्स की गणना कर सकते हैं, इसलिए आपके पास 'कुछ भी नहीं' के इन विशाल क्षेत्रों में चिपके हुए नहीं हैं। अंतिम परिणाम इस तरह दिखेगा: