পাইথনের সাথে অনুভূমিকভাবে বেশ কয়েকটি চিত্র একত্রিত করুন


121

আমি পাইথনের কিছু জেপিইজি চিত্র অনুভূমিকভাবে একত্রিত করার চেষ্টা করছি।

সমস্যা

আমার কাছে 3 টি চিত্র রয়েছে - প্রতিটির 148 x 95 - সংযুক্ত দেখুন। আমি একই চিত্রের 3 টি অনুলিপি তৈরি করেছি - সে কারণেই তারা একই।

এখানে চিত্র বর্ণনা লিখুনএখানে চিত্র বর্ণনা লিখুনএখানে চিত্র বর্ণনা লিখুন

আমার চেষ্টা

আমি নীচের কোডটি ব্যবহার করে তাদের সাথে আনুভূমিকভাবে যোগদানের চেষ্টা করছি:

import sys
from PIL import Image

list_im = ['Test1.jpg','Test2.jpg','Test3.jpg']
new_im = Image.new('RGB', (444,95)) #creates a new empty image, RGB mode, and size 444 by 95

for elem in list_im:
    for i in xrange(0,444,95):
        im=Image.open(elem)
        new_im.paste(im, (i,0))
new_im.save('test.jpg')

যাইহোক, এটি হিসাবে সংযুক্ত আউটপুট উত্পাদন করছে test.jpg

এখানে চিত্র বর্ণনা লিখুন

প্রশ্ন

এই চিত্রগুলিকে আনুভূমিকভাবে সংহত করার কোনও উপায় আছে যে পরীক্ষার উপ-চিত্রগুলিতে টেস্ট.জেপিজি-তে কোনও অতিরিক্ত আংশিক চিত্র প্রদর্শিত হচ্ছে না?

অতিরিক্ত তথ্য

আমি অনুভূমিকভাবে এন ইমেজকে একত্রিত করার একটি উপায় খুঁজছি। আমি এই কোডটি সাধারণত ব্যবহার করতে চাই তাই আমি পছন্দ করতে চাই:

  • যদি সম্ভব হয় তবে হার্ড-কোড চিত্রের মাত্রা নয়
  • এক লাইনে মাত্রা নির্দিষ্ট করুন যাতে সেগুলি সহজেই পরিবর্তন করা যায়

2
কেন for i in xrange(...)আপনার কোড একটি আছে ? pasteআপনার উল্লেখ করা তিনটি চিত্র ফাইলের যত্ন নেওয়া উচিত নয় ?
এমএসডব্লিউ

প্রশ্ন, আপনার চিত্রগুলি সবসময় একই আকার হবে?
dermen


dermen: হ্যাঁ, চিত্রগুলি সর্বদা একই আকারের হবে। এমএসডব্লিউ: মাঝে মাঝে ফাঁকা জায়গা না রেখে কীভাবে চিত্রগুলি লুপ করবেন তা নিশ্চিত ছিলাম না - আমার পদ্ধতির ব্যবহার সম্ভবত সবচেয়ে ভাল নয়।
এডেজ

উত্তর:


171

আপনি এর মতো কিছু করতে পারেন:

import sys
from PIL import Image

images = [Image.open(x) for x in ['Test1.jpg', 'Test2.jpg', 'Test3.jpg']]
widths, heights = zip(*(i.size for i in images))

total_width = sum(widths)
max_height = max(heights)

new_im = Image.new('RGB', (total_width, max_height))

x_offset = 0
for im in images:
  new_im.paste(im, (x_offset,0))
  x_offset += im.size[0]

new_im.save('test.jpg')

Test1.jpg

Test1.jpg

Test2.jpg

Test2.jpg

Test3.jpg

Test3.jpg

test.jpg

এখানে চিত্র বর্ণনা লিখুন


নেস্টেড for i in xrange(0,444,95):প্রতিটি ইমেজ 5 বার আটকানো হয়, 95 পিক্সেল পৃথক বিস্মিত। প্রতিটি বহিরাগত লুপ পুনরাবৃত্তি পূর্ববর্তী উপর আটকানো।

for elem in list_im:
  for i in xrange(0,444,95):
    im=Image.open(elem)
    new_im.paste(im, (i,0))
  new_im.save('new_' + elem + '.jpg')

এখানে চিত্র বর্ণনা লিখুন এখানে চিত্র বর্ণনা লিখুন এখানে চিত্র বর্ণনা লিখুন


দুটি প্রশ্ন: 1. x_offset = 0- এটি কি চিত্র কেন্দ্রগুলির মধ্যে বিচলিত? ২. উল্লম্ব বক্তব্য রাখার জন্য, আপনার দৃষ্টিভঙ্গি কীভাবে পরিবর্তন হয়?
এডেজ

2
পেস্টের দ্বিতীয় যুক্তিটি একটি বাক্স। "বাক্স আর্গুমেন্টটি হয় 2-টিপল যা উপরের বাম কোণে প্রদান করে, একটি 4-টিউপল বাম, উপরের, ডান এবং নীচে পিক্সেল স্থানাঙ্ককে সংজ্ঞায়িত করে বা কোনওটি (0 (0)) এর মতো নয়" " সুতরাং 2-tuple মধ্যে আমরা হিসাবে ব্যবহার করা x_offsetহয় left। উল্লম্ব সংক্ষিপ্তসার জন্য y-offset, এবং এর উপর নজর রাখুন top। এর পরিবর্তে sum(widths)এবং করুন max(height), sum(heights)এবং max(widths)2-টিউপল বাক্সের দ্বিতীয় যুক্তি ব্যবহার করুন। বাড়ায় y_offsetদ্বারা im.size[1]
ডিটিিং

21
সুন্দর সমাধান। অজগর 3 এ নোট করুন যে মানচিত্রগুলি কেবল একবারে পুনরাবৃত্তি হতে পারে, তাই আপনাকে দ্বিতীয়বার চিত্রগুলি পুনরাবৃত্ত করার আগে আবার চিত্রগুলি = মানচিত্র (চিত্র। ওপেন, চিত্র_ফায়ালগুলি) করতে হবে।
নাইবাবা

1
জয়জাবা আমিও আপনার বর্ণিত সমস্যার মধ্যে দৌড়েছি, তাই আমি মানচিত্রের পরিবর্তে একটি তালিকা বোধগম্যতা ব্যবহারের জন্য ডিটিংয়ের সমাধান সম্পাদনা করেছি।
বেন কুইগলি

1
mapপাইথন ৩..6-এর পরিবর্তে তালিকা বোধগম্যতা আমাকে ব্যবহার করতে হয়েছিল
ক্লিমেন্টওয়াল্টার

89

আমি এটি চেষ্টা করবে:

import numpy as np
import PIL
from PIL import Image

list_im = ['Test1.jpg', 'Test2.jpg', 'Test3.jpg']
imgs    = [ PIL.Image.open(i) for i in list_im ]
# pick the image which is the smallest, and resize the others to match it (can be arbitrary image shape here)
min_shape = sorted( [(np.sum(i.size), i.size ) for i in imgs])[0][1]
imgs_comb = np.hstack( (np.asarray( i.resize(min_shape) ) for i in imgs ) )

# save that beautiful picture
imgs_comb = PIL.Image.fromarray( imgs_comb)
imgs_comb.save( 'Trifecta.jpg' )    

# for a vertical stacking it is simple: use vstack
imgs_comb = np.vstack( (np.asarray( i.resize(min_shape) ) for i in imgs ) )
imgs_comb = PIL.Image.fromarray( imgs_comb)
imgs_comb.save( 'Trifecta_vertical.jpg' )

যতক্ষণ না সমস্ত চিত্র একই জাতের (সমস্ত আরজিবি, সমস্ত আরজিবিএ, বা সমস্ত গ্রেস্কেল) কাজ করা উচিত। কোডটির আরও কয়েকটি লাইনের ক্ষেত্রে এটি নিশ্চিত হওয়া কঠিন হওয়া উচিত নয়। এখানে আমার উদাহরণ চিত্র এবং ফলাফল:

Test1.jpg

Test1.jpg

Test2.jpg

Test2.jpg

Test3.jpg

Test3.jpg

Trifecta.jpg:

সম্মিলিত ছবি

Trifecta_vertical.jpg

এখানে চিত্র বর্ণনা লিখুন


অনেক ধন্যবাদ. আর একটি ভাল উত্তর। কিভাবে min_shape =....এবং imgs_comb....একটি উল্লম্ব বক্তৃতা জন্য পরিবর্তন হবে ? আপনি কি এখানে মন্তব্য হিসাবে পোস্ট করতে পারেন, বা আপনার জবাবে?
এডেজ

3
উল্লম্ব জন্য, পরিবর্তন hstackকরার জন্য vstack
dermen

আরও একটি প্রশ্ন: আপনার প্রথম চিত্র ( Test1.jpg ) অন্যান্য চিত্রের চেয়ে বড়। আপনার চূড়ান্ত (অনুভূমিক বা উল্লম্ব) সংক্ষিপ্ত চিত্রে, সমস্ত চিত্র একই আকারের। আপনি কী ব্যাখ্যা করতে পারবেন যে আপনি কীভাবে প্রথম চিত্রটি সংক্ষেপণের আগে সংকুচিত করতে সক্ষম হয়েছিলেন?
এডিজ

আমি Image.resizeপিআইএল থেকে ব্যবহার করেছি । min_shape(মিনি_উইথ, মিনি_ হাইট) এর একটি টিপল এবং তারপরে (np.asarray( i.resize(min_shape) ) for i in imgs )সমস্ত চিত্রগুলি আকারে সঙ্কুচিত করবে। আসলে, min_shapeআপনি যে কোনও (width,height)ইচ্ছা করতে পারেন , কেবল মনে রাখবেন যে লো-রেজিস ইমেজগুলি বাড়ানো তাদের ঝাপসা করে দেবে!
dermen

3
আপনি যদি কোনও সুনির্দিষ্ট ছাড়াই চিত্রগুলি একত্রিত করতে চান তবে এটি সম্ভবত এখানে সবচেয়ে সহজ এবং সবচেয়ে নমনীয় উত্তর। এটি চিত্রের আকারের ভিন্নতা, যে কোনও # চিত্র এবং বিভিন্ন চিত্র বিন্যাসের জন্য অ্যাকাউন্ট করে। এটি খুব সুচিন্তিত উত্তর এবং অত্যন্ত দরকারী useful কখনই ন্যাপি ব্যবহার করার কথা ভাবেনি। ধন্যবাদ.
নোটসটল

26

সম্পাদনা করুন: পিটিআইএল ব্যবহার করার কারণে ডিটিংয়ের উত্তরটি আপনার প্রশ্নের ক্ষেত্রে আরও বেশি প্রযোজ্য, তবে আপনি কীভাবে আর্দ্রভাবে এটি করবেন তা জানতে চাইলে আমি এটি ছেড়ে দেব।

এখানে একটি নম্পী / ম্যাটপ্ল্লোলিব সমাধান রয়েছে যা কোনও আকার / আকারের এন চিত্রগুলির জন্য (কেবল রঙের চিত্রগুলি) কাজ করা উচিত।

import numpy as np
import matplotlib.pyplot as plt

def concat_images(imga, imgb):
    """
    Combines two color image ndarrays side-by-side.
    """
    ha,wa = imga.shape[:2]
    hb,wb = imgb.shape[:2]
    max_height = np.max([ha, hb])
    total_width = wa+wb
    new_img = np.zeros(shape=(max_height, total_width, 3))
    new_img[:ha,:wa]=imga
    new_img[:hb,wa:wa+wb]=imgb
    return new_img

def concat_n_images(image_path_list):
    """
    Combines N color images from a list of image paths.
    """
    output = None
    for i, img_path in enumerate(image_path_list):
        img = plt.imread(img_path)[:,:,:3]
        if i==0:
            output = img
        else:
            output = concat_images(output, img)
    return output

এখানে উদাহরণস্বরূপ ব্যবহার:

>>> images = ["ronda.jpeg", "rhod.jpeg", "ronda.jpeg", "rhod.jpeg"]
>>> output = concat_n_images(images)
>>> import matplotlib.pyplot as plt
>>> plt.imshow(output)
>>> plt.show()

এখানে চিত্র বর্ণনা লিখুন


তোমার output = concat_images(output, ...আমি আমি এই কাজ করতে একটি উপায় জন্য অনুসন্ধান শুরু খুঁজছেন হয়। ধন্যবাদ।
এডেজ

হাই বলস্যাটবলসডটবলস, আপনার উত্তর সম্পর্কে আমার একটি প্রশ্ন আছে। আমি যদি প্রতিটি উপ-চিত্রের জন্য উপ-শিরোনাম যুক্ত করতে চাই তবে কীভাবে এটি করবেন? ধন্যবাদ।
ব্যবহারকারী 297850

12

ডিটিংয়ের উত্তরের ভিত্তিতে আমি একটি ফাংশন তৈরি করেছি যা ব্যবহার করা সহজ:

from PIL import Image


def append_images(images, direction='horizontal',
                  bg_color=(255,255,255), aligment='center'):
    """
    Appends images in horizontal/vertical direction.

    Args:
        images: List of PIL images
        direction: direction of concatenation, 'horizontal' or 'vertical'
        bg_color: Background color (default: white)
        aligment: alignment mode if images need padding;
           'left', 'right', 'top', 'bottom', or 'center'

    Returns:
        Concatenated image as a new PIL image object.
    """
    widths, heights = zip(*(i.size for i in images))

    if direction=='horizontal':
        new_width = sum(widths)
        new_height = max(heights)
    else:
        new_width = max(widths)
        new_height = sum(heights)

    new_im = Image.new('RGB', (new_width, new_height), color=bg_color)


    offset = 0
    for im in images:
        if direction=='horizontal':
            y = 0
            if aligment == 'center':
                y = int((new_height - im.size[1])/2)
            elif aligment == 'bottom':
                y = new_height - im.size[1]
            new_im.paste(im, (offset, y))
            offset += im.size[0]
        else:
            x = 0
            if aligment == 'center':
                x = int((new_width - im.size[0])/2)
            elif aligment == 'right':
                x = new_width - im.size[0]
            new_im.paste(im, (x, offset))
            offset += im.size[1]

    return new_im

এটি একটি পটভূমির রঙ এবং চিত্র প্রান্তিককরণ চয়ন করার অনুমতি দেয়। এটি পুনরাবৃত্তি করাও সহজ:

images = map(Image.open, ['hummingbird.jpg', 'tiger.jpg', 'monarch.png'])

combo_1 = append_images(images, direction='horizontal')
combo_2 = append_images(images, direction='horizontal', aligment='top',
                        bg_color=(220, 140, 60))
combo_3 = append_images([combo_1, combo_2], direction='vertical')
combo_3.save('combo_3.png')

সংক্ষিপ্ত চিত্রের উদাহরণ


8

পূর্ববর্তী পন্থাগুলি সাধারণকরণের একটি ফাংশন এখানে রয়েছে, পিআইএল-তে চিত্রগুলির গ্রিড তৈরি করে:

from PIL import Image
import numpy as np

def pil_grid(images, max_horiz=np.iinfo(int).max):
    n_images = len(images)
    n_horiz = min(n_images, max_horiz)
    h_sizes, v_sizes = [0] * n_horiz, [0] * (n_images // n_horiz)
    for i, im in enumerate(images):
        h, v = i % n_horiz, i // n_horiz
        h_sizes[h] = max(h_sizes[h], im.size[0])
        v_sizes[v] = max(v_sizes[v], im.size[1])
    h_sizes, v_sizes = np.cumsum([0] + h_sizes), np.cumsum([0] + v_sizes)
    im_grid = Image.new('RGB', (h_sizes[-1], v_sizes[-1]), color='white')
    for i, im in enumerate(images):
        im_grid.paste(im, (h_sizes[i % n_horiz], v_sizes[i // n_horiz]))
    return im_grid

এটি গ্রিডের প্রতিটি সারি এবং কলামগুলিকে সর্বনিম্ন সঙ্কুচিত করবে। পাইল_গ্রিড (চিত্রগুলি) ব্যবহার করে আপনার কেবল একটি সারি বা পাইল_গ্রিড (চিত্রগুলি, 1) ব্যবহার করে কেবল একটি কলাম থাকতে পারে।

নিম্পি-অ্যারে ভিত্তিক সমাধানগুলির ওপরে পিআইএল ব্যবহারের একটি সুবিধা হ'ল আপনি আলাদাভাবে কাঠামোগত চিত্রগুলি (যেমন গ্রেস্কেল বা প্যালেট ভিত্তিক চিত্রগুলির সাথে) ব্যবহার করতে পারেন।

উদাহরণ আউটপুট

def dummy(w, h):
    "Produces a dummy PIL image of given dimensions"
    from PIL import ImageDraw
    im = Image.new('RGB', (w, h), color=tuple((np.random.rand(3) * 255).astype(np.uint8)))
    draw = ImageDraw.Draw(im)
    points = [(i, j) for i in (0, im.size[0]) for j in (0, im.size[1])]
    for i in range(len(points) - 1):
        for j in range(i+1, len(points)):
            draw.line(points[i] + points[j], fill='black', width=2)
    return im

dummy_images = [dummy(20 + np.random.randint(30), 20 + np.random.randint(30)) for _ in range(10)]

pil_grid(dummy_images):

line.png

pil_grid(dummy_images, 3):

এখানে চিত্র বর্ণনা লিখুন

pil_grid(dummy_images, 1):

এখানে চিত্র বর্ণনা লিখুন


পাইল_গ্রিডে এই লাইনটি h_sizes, v_sizes = [0] * n_horiz, [0] * (n_images // n_horiz) পড়তে হবে: h_sizes, v_sizes = [0] * n_horiz, [0] * ((n_images // n_horiz) + (1 if n_images % n_horiz > 0 else 0)) কারণ: অনুভূমিক প্রস্থটি যদি পূর্ণসংখ্যায় চিত্রের সংখ্যা বিভাজিত না করে তবে আপনার অতিরিক্ত অসম্পূর্ণ লাইনের জন্য সংযোজন করতে হবে।
বার্নহার্ড ওয়াগনার

3

যদি সমস্ত চিত্রের উচ্চতা এক হয়,

imgs = [‘a.jpg’, b.jpg’, c.jpg’]
concatenated = Image.fromarray(
  np.concatenate(
    [np.array(Image.open(x)) for x in imgs],
    axis=1
  )
)

সম্ভবত আপনি এই মত কনটেন্টেশন আগে ইমেজ আকার পরিবর্তন করতে পারেন,

imgs = [‘a.jpg’, b.jpg’, c.jpg’]
concatenated = Image.fromarray(
  np.concatenate(
    [np.array(Image.open(x).resize((640,480)) for x in imgs],
    axis=1
  )
)

1
সহজ এবং সহজ। ধন্যবাদ
মাইক ডি ক্লার্ক

2

এখানে আমার সমাধান:

from PIL import Image


def join_images(*rows, bg_color=(0, 0, 0, 0), alignment=(0.5, 0.5)):
    rows = [
        [image.convert('RGBA') for image in row]
        for row
        in rows
    ]

    heights = [
        max(image.height for image in row)
        for row
        in rows
    ]

    widths = [
        max(image.width for image in column)
        for column
        in zip(*rows)
    ]

    tmp = Image.new(
        'RGBA',
        size=(sum(widths), sum(heights)),
        color=bg_color
    )

    for i, row in enumerate(rows):
        for j, image in enumerate(row):
            y = sum(heights[:i]) + int((heights[i] - image.height) * alignment[1])
            x = sum(widths[:j]) + int((widths[j] - image.width) * alignment[0])
            tmp.paste(image, (x, y))

    return tmp


def join_images_horizontally(*row, bg_color=(0, 0, 0), alignment=(0.5, 0.5)):
    return join_images(
        row,
        bg_color=bg_color,
        alignment=alignment
    )


def join_images_vertically(*column, bg_color=(0, 0, 0), alignment=(0.5, 0.5)):
    return join_images(
        *[[image] for image in column],
        bg_color=bg_color,
        alignment=alignment
    )

এই চিত্রগুলির জন্য:

images = [
    [Image.open('banana.png'), Image.open('apple.png')],
    [Image.open('lime.png'), Image.open('lemon.png')],
]

ফলাফলগুলি দেখতে পাবেন:


join_images(
    *images,
    bg_color='green',
    alignment=(0.5, 0.5)
).show()

এখানে চিত্র বর্ণনা লিখুন


join_images(
    *images,
    bg_color='green',
    alignment=(0, 0)

).show()

এখানে চিত্র বর্ণনা লিখুন


join_images(
    *images,
    bg_color='green',
    alignment=(1, 1)
).show()

এখানে চিত্র বর্ণনা লিখুন


1
""" 
merge_image takes three parameters first two parameters specify 
the two images to be merged and third parameter i.e. vertically
is a boolean type which if True merges images vertically
and finally saves and returns the file_name
"""
def merge_image(img1, img2, vertically):
    images = list(map(Image.open, [img1, img2]))
    widths, heights = zip(*(i.size for i in images))
    if vertically:
        max_width = max(widths)
        total_height = sum(heights)
        new_im = Image.new('RGB', (max_width, total_height))

        y_offset = 0
        for im in images:
            new_im.paste(im, (0, y_offset))
            y_offset += im.size[1]
    else:
        total_width = sum(widths)
        max_height = max(heights)
        new_im = Image.new('RGB', (total_width, max_height))

        x_offset = 0
        for im in images:
            new_im.paste(im, (x_offset, 0))
            x_offset += im.size[0]

    new_im.save('test.jpg')
    return 'test.jpg'

1
from __future__ import print_function
import os
from pil import Image

files = [
      '1.png',
      '2.png',
      '3.png',
      '4.png']

result = Image.new("RGB", (800, 800))

for index, file in enumerate(files):
path = os.path.expanduser(file)
img = Image.open(path)
img.thumbnail((400, 400), Image.ANTIALIAS)
x = index // 2 * 400
y = index % 2 * 400
w, h = img.size
result.paste(img, (x, y, x + w, y + h))

result.save(os.path.expanduser('output.jpg'))

আউটপুট

এখানে চিত্র বর্ণনা লিখুন


0

ইতিমধ্যে প্রস্তাবিত সমাধানগুলিতে কেবল যুক্ত করা। একই উচ্চতা ধরে নেয়, কোন আকার নেই।

import sys
import glob
from PIL import Image
Image.MAX_IMAGE_PIXELS = 100000000  # For PIL Image error when handling very large images

imgs    = [ Image.open(i) for i in list_im ]

widths, heights = zip(*(i.size for i in imgs))
total_width = sum(widths)
max_height = max(heights)

new_im = Image.new('RGB', (total_width, max_height))

# Place first image
new_im.paste(imgs[0],(0,0))

# Iteratively append images in list horizontally
hoffset=0
for i in range(1,len(imgs),1):
    **hoffset=imgs[i-1].size[0]+hoffset  # update offset**
    new_im.paste(imgs[i],**(hoffset,0)**)

new_im.save('output_horizontal_montage.jpg')

0

আমার সমাধানটি হবে:

import sys
import os
from PIL import Image, ImageFilter
from PIL import ImageFont
from PIL import ImageDraw 

os.chdir('C:/Users/Sidik/Desktop/setup')
print(os.getcwd())

image_list= ['IMG_7292.jpg','IMG_7293.jpg','IMG_7294.jpg', 'IMG_7295.jpg' ]

image = [Image.open(x) for x in image_list]  # list
im_1 = image[0].rotate(270)
im_2 = image[1].rotate(270)
im_3 = image[2].rotate(270)
#im_4 = image[3].rotate(270)

height = image[0].size[0]
width = image[0].size[1]
# Create an empty white image frame
new_im = Image.new('RGB',(height*2,width*2),(255,255,255))

new_im.paste(im_1,(0,0))
new_im.paste(im_2,(height,0))
new_im.paste(im_3,(0,width))
new_im.paste(im_4,(height,width))


draw = ImageDraw.Draw(new_im)
font = ImageFont.truetype('arial',200)

draw.text((0, 0), '(a)', fill='white', font=font)
draw.text((height, 0), '(b)', fill='white', font=font)
draw.text((0, width), '(c)', fill='white', font=font)
#draw.text((height, width), '(d)', fill='white', font=font)

new_im.show()
new_im.save('BS1319.pdf')   
[![Laser spots on the edge][1]][1]
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.