Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Скриптовые языки программирования > Python
Регистрация

Восстановить пароль

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 27.01.2025, 15:29   #41
MakarovDs
Форумчанин
 
Аватар для MakarovDs
 
Регистрация: 10.01.2020
Сообщений: 350
По умолчанию

Теперь нужно к мозаичному генератору применить эффект размытия
Код:
import tkinter as tk
from tkinter import filedialog, messagebox
import numpy as np
import pygame
from threading import Thread
from PIL import Image, ImageTk
from moviepy.editor import VideoFileClip
import random
from pydub import AudioSegment
import tempfile
import os
import time
import cv2

class AudioMosaic:
    def __init__(self):
        self.segments = []
        self.sample_rate = 0
        self.is_playing = False
        pygame.mixer.init()

    def convert_audio_to_segments(self, audio, segment_duration_ms=500):
        self.segments = []
        current_time = 0

        while current_time < len(audio):
            segment = audio[current_time:current_time + segment_duration_ms]
            self.segments.append(segment.raw_data)
            current_time += segment_duration_ms
        
        self.sample_rate = audio.frame_rate

    def mix_audio_segments(self):
        random.shuffle(self.segments)
        return b''.join(self.segments)

    def play_audio(self):
        self.is_playing = True
        while self.is_playing:
            shuffled_audio = self.mix_audio_segments()
            sound_array = np.frombuffer(shuffled_audio, dtype=np.int16)
            pygame.mixer.Sound(buffer=sound_array).play()

            # Даем время на воспроизведение сегментов
            time.sleep(len(shuffled_audio) / (self.sample_rate * 2))

    def stop_audio(self):
        self.is_playing = False
        pygame.mixer.stop()

video_clips = []
audio_mosaic = AudioMosaic()

def load_videos():
    global video_clips
    video_paths = filedialog.askopenfilenames(title="Выберите видео файлы", filetypes=[("Video files", "*.mp4;*.avi;*.mov")])
    if video_paths:
        for video_path in video_paths:
            video_clip = VideoFileClip(video_path)
            video_clips.append((video_path, video_clip))
            video_listbox.insert(tk.END, video_path)

def shuffle_frame(frame, iterations=6):
    plitkorez = 2
    height, width, _ = frame.shape
    h, w = height // (plitkorez ** iterations), width // (plitkorez ** iterations)
    
    tiles = []
    for i in range(plitkorez ** iterations):
        for j in range(plitkorez ** iterations):
            y_start = i * h
            y_end = (i + 1) * h if (i + 1) * h < height else height
            x_start = j * w
            x_end = (j + 1) * w if (j + 1) * w < width else width
            tiles.append(frame[y_start:y_end, x_start:x_end])

    random.shuffle(tiles)

    reshuffled_frame = []
    for i in range(plitkorez ** iterations):
        reshuffled_frame.append(np.hstack(tiles[i * (plitkorez ** iterations):(i + 1) * (plitkorez ** iterations)]))

    return np.vstack(reshuffled_frame)

def blur_frame(frame, blur_strength=41):  # Размываем весь кадр
    return cv2.GaussianBlur(frame, (blur_strength, blur_strength), 0)

def display_random_frame():
    if video_clips:
        video_clip = random.choice(video_clips)[1]
        start_time = random.uniform(0, video_clip.duration - 1)
        frame = video_clip.get_frame(start_time)
        frame_array = np.array(Image.fromarray(frame).resize((640, 480), Image.LANCZOS))
        
        # Перемешиваем плитки
        shuffled_frame = shuffle_frame(frame_array)

        # Применяем размытие
        blurred_frame = blur_frame(shuffled_frame)

        # Преобразуем в изображение для tkinter
        blurred_frame_photo = ImageTk.PhotoImage(Image.fromarray(blurred_frame))

        # Отображаем изображение
        canvas.create_image(0, 0, anchor=tk.NW, image=blurred_frame_photo)
        canvas.image = blurred_frame_photo

    canvas.after(1000, display_random_frame)

def start_video():
    global video_clips
    if not video_clips:
        messagebox.showwarning("Предупреждение", "Выберите видео файлы сначала.")
        return
        
    audio_segments = []
    for video_path, video_clip in video_clips:
        with tempfile.NamedTemporaryFile(suffix=".wav", delete=False) as temp_audio_file:
            audio_path = temp_audio_file.name
            video_clip.audio.write_audiofile(audio_path)
            audio_segment = AudioSegment.from_file(audio_path)

            audio_segments.append(audio_segment)

        os.remove(audio_path)  # Удаляем файл после использования

    combined_audio = sum(audio_segments)
    audio_mosaic.convert_audio_to_segments(combined_audio)
    Thread(target=audio_mosaic.play_audio, daemon=True).start()  
    display_random_frame()  

# Создание графического интерфейса
root = tk.Tk()
root.title("Генератор случайного видео")

canvas = tk.Canvas(root, width=640, height=480)
canvas.pack()

video_listbox = tk.Listbox(root, width=80, height=10)
video_listbox.pack()

select_button = tk.Button(root, text="Выбрать видео", command=load_videos)
select_button.pack()

start_button = tk.Button(root, text="Старт видео", command=start_video)
start_button.pack()

# Запустить основной цикл интерфейса
root.mainloop()
Вот код примера -> Ссылка.

Последний раз редактировалось MakarovDs; 28.01.2025 в 14:01.
MakarovDs на форуме Ответить с цитированием
Старый 27.01.2025, 18:22   #42
MakarovDs
Форумчанин
 
Аватар для MakarovDs
 
Регистрация: 10.01.2020
Сообщений: 350
По умолчанию

Теперь нам нужно сделать перемещение в этом пространстве вот что у меня получилось -> Код. Но нужно немного подождать.

Что-бы перемещаться используйте клавиши qweasd для перемещения по всем осям координат.

Последний раз редактировалось MakarovDs; 28.01.2025 в 10:42.
MakarovDs на форуме Ответить с цитированием
Старый 28.01.2025, 14:37   #43
MakarovDs
Форумчанин
 
Аватар для MakarovDs
 
Регистрация: 10.01.2020
Сообщений: 350
По умолчанию

Теперь мы можем добавить вторую версию генератора случайного видел, и изменить генератор случайного видео цветного шума что-бы добавить возможность перемещения в пространстве.



Вот код -> Ссылка.
MakarovDs на форуме Ответить с цитированием
Старый 28.01.2025, 14:51   #44
MakarovDs
Форумчанин
 
Аватар для MakarovDs
 
Регистрация: 10.01.2020
Сообщений: 350
По умолчанию

Но все кадры в видео остановлены а нужно что-бы оно генерировалось на ходу, и я мог в нём перемещаться:

Вот код -> Ссылка.

Последний раз редактировалось MakarovDs; 29.01.2025 в 08:40.
MakarovDs на форуме Ответить с цитированием
Старый 01.02.2025, 12:56   #45
MakarovDs
Форумчанин
 
Аватар для MakarovDs
 
Регистрация: 10.01.2020
Сообщений: 350
По умолчанию

Короче сделал микрофонную версию Хоруса, короче потом вернусь к этому коду если понадобиться...
Код:
import tkinter as tk
import pyaudio
import threading
import numpy as np
from collections import deque

# Константы для настройки аудио
CHUNK = 1024  # Количество фреймов за раз
FORMAT = pyaudio.paInt16  # Формат звука
CHANNELS = 1  # Количество каналов
RATE = 44100  # Частота дискретизации

is_recording = False
audio_buffer = deque(maxlen=44100)  # Буфер для аудио (например, 1 секунда звука)

def process_audio(input_device_index):
    global is_recording
    audio = pyaudio.PyAudio()
    
    stream_input = audio.open(
        format=FORMAT,
        channels=CHANNELS,
        rate=RATE,
        input=True,
        frames_per_buffer=CHUNK,
        input_device_index=input_device_index
    )

    print("Запись аудио... Чтобы остановить запись, нажмите 'Стоп'.")
    is_recording = True

    try:
        while is_recording:
            data = stream_input.read(CHUNK)
            audio_buffer.append(data)  # Запись аудио в буфер

    except Exception as e:
        print(f"Ошибка записи: {e}")

    finally:
        stream_input.stop_stream()
        stream_input.close()
        audio.terminate()

def start_recording():
    global is_recording
    input_device_index = int(input_device_entry.get().strip())
    
    is_recording = True
    
    # Запускаем запись в отдельном потоке
    recording_thread = threading.Thread(target=process_audio, args=(input_device_index,), daemon=True)
    recording_thread.start()

def stop_recording():
    global is_recording
    is_recording = False

def apply_chorus_effect(data):
    """Применение эффекта хорус."""
    audio_data = list(data)  # Преобразуем данные в список байтов

    # Длина заголовка (может варьироваться в зависимости от формата аудио)
    header_length = 100  
    data_to_shuffle = audio_data[header_length:]

    # Перемешивание случайных блоков
    block_size = 64  # Размер блока для перемешивания
    num_blocks = len(data_to_shuffle) // block_size

    # Создание блоков
    blocks = [data_to_shuffle[i * block_size:(i + 1) * block_size] for i in range(num_blocks)]
    
    # Перемешивание блоков
    np.random.shuffle(blocks)

    # Объединение блоков обратно
    shuffled_data = [byte for block in blocks for byte in block]
    
    # Объединяем заголовок и перемешанные данные
    shuffled_byte_data = audio_data[:header_length] + shuffled_data
    
    # Преобразование обратно в байты
    return bytes(shuffled_byte_data)

def play_recorded_audio():
    global audio_buffer
    if len(audio_buffer) == 0:
        print("Нет записанного аудио для воспроизведения.")
        return

    audio = pyaudio.PyAudio()
    stream_output = audio.open(
        format=FORMAT,
        channels=CHANNELS,
        rate=RATE,
        output=True
    )

    # Воспроизведение записанных данных из буфера с эффектом хорус
    for data in audio_buffer:
        chorus_data = apply_chorus_effect(data)  # Применение эффекта хорус
        stream_output.write(chorus_data)

    stream_output.stop_stream()
    stream_output.close()
    audio.terminate()

def list_audio_devices():
    audio = pyaudio.PyAudio()
    device_list = []
    
    for i in range(audio.get_device_count()):
        device_info = audio.get_device_info_by_index(i)
        device_list.append(f"{i}: {device_info['name']}")
        
    audio.terminate()
    return device_list

# Создание графического интерфейса
root = tk.Tk()
root.title("Конвертер аудио")
root.geometry("320x220")  # Измененный размер окна

# Поля для ввода индексов устройств
tk.Label(root, text="Индекс записи устройства:").pack()
input_device_entry = tk.Entry(root)
input_device_entry.insert(0, "0")  # Установка значения по умолчанию на 0
input_device_entry.pack()

start_button = tk.Button(root, text="Запись аудио", command=start_recording)
start_button.pack(pady=10)

stop_button = tk.Button(root, text="Стоп", command=stop_recording)
stop_button.pack(pady=10)

play_button = tk.Button(root, text="Воспроизвести записанное", command=play_recorded_audio)
play_button.pack(pady=10)

# Заполнение индексов устройств
audio_devices = list_audio_devices()
for device in audio_devices:
    print(device)
    if 'Microphone' in device:  # Проверка на наличие слова 'Microphone'
        input_device_entry.insert(0, device.split(":")[0])  # Устанавливаем значение по умолчанию для микрофона

# Запустить основной цикл интерфейса
root.mainloop()
Только не пойму звук почему отличается от того который в 26 комментарии кода...

Ссылка на гитхаб.

Последний раз редактировалось MakarovDs; 01.02.2025 в 17:40.
MakarovDs на форуме Ответить с цитированием
Старый 04.02.2025, 19:07   #46
MakarovDs
Форумчанин
 
Аватар для MakarovDs
 
Регистрация: 10.01.2020
Сообщений: 350
По умолчанию

В пятой версии я добавил возможность перемещения по кнопкам в окне, и так же сид мира который формирует карту изображений кадров, и с таблом координат.

Код:
import tkinter as tk
import numpy as np
from PIL import Image, ImageTk
import pygame
import threading

# Инициализация Pygame
pygame.mixer.init()

# Параметры
video_window = None
canvas = None

# Начальные координаты и сид
x, y, z = 0, 0, 0
seed = 42

def generate_random_audio(sample_rate=44100, duration=1):
    audio_data = np.random.uniform(-1, 1, int(sample_rate * duration)).astype(np.float32)
    return audio_data

def generate_random_video(seed, width=640, height=480):
    np.random.seed(seed)
    return np.random.randint(0, 256, (height, width, 3), dtype=np.uint8)

def play_sound():
    sample_rate = 44100
    while True:
        sound = generate_random_audio(sample_rate)
        sound = (sound * 32767).astype(np.int16)
        pygame.mixer.Sound(buffer=sound.tobytes()).play()
        pygame.time.delay(100)

def display_video():
    global video_window, canvas
    video_window = tk.Toplevel()
    video_window.title("Random Video")

    canvas = tk.Canvas(video_window, width=640, height=480)
    canvas.pack()

    update_frame()  # Первый кадр

def start_audio_and_video():
    thread = threading.Thread(target=play_sound, daemon=True)
    thread.start()
    display_video()

def update_frame():
    if canvas:
        # Генерация нового сида на основе координат и текущего сида из поля
        current_seed = (x * 10000 + y * 100 + z + seed) % (2**32)
        frame = generate_random_video(current_seed)  # Генерация нового кадра с использованием сида
        frame_image = Image.fromarray(frame)
        frame_image = ImageTk.PhotoImage(frame_image)

        # Обновление Canvas
        canvas.delete('all')
        canvas.create_image(0, 0, anchor=tk.NW, image=frame_image)
        canvas.image = frame_image  # Сохраняем ссылку для предотвращения сборки мусора

def update_coordinates_display():
    coordinates_label.config(text=f"Координаты - x: {x}, y: {y}, z: {z}, Seed: {seed}")

def move_left():
    global x
    x -= 1
    update_frame()
    update_coordinates_display()

def move_right():
    global x
    x += 1
    update_frame()
    update_coordinates_display()

def move_up():
    global y
    y += 1
    update_frame()
    update_coordinates_display()

def move_down():
    global y
    y -= 1
    update_frame()
    update_coordinates_display()

def set_seed():
    global seed
    try:
        seed = int(seed_entry.get())
        update_frame()  # Обновление кадра с новым сидом
        update_coordinates_display()  # Обновление отображения координат
    except ValueError:
        seed_entry.delete(0, tk.END)
        seed_entry.insert(0, str(seed))  # Восстановление введённого значения, если ввод некорректен

def validate_seed_input(event):
    current_value = seed_entry.get()
    if not current_value.isdigit():
        seed_entry.delete(0, tk.END)
        seed_entry.insert(0, ''.join(filter(str.isdigit, current_value)))  # Удалить некорректные символы

# Создание основного окна
root = tk.Tk()
root.title("Procedural Audio and Video")
root.geometry("320x200")

start_button = tk.Button(root, text="Start", command=start_audio_and_video)
start_button.pack()

coordinates_label = tk.Label(root, text=f"Координаты - x: {x}, y: {y}, z: {z}, Seed: {seed}")
coordinates_label.pack()

seed_entry = tk.Entry(root)
seed_entry.pack()
seed_entry.insert(0, str(seed))  # Ввод сида по умолчанию

seed_entry.bind('<KeyRelease>', validate_seed_input)  # Проверка ввода сида

set_seed_button = tk.Button(root, text="Установить сид", command=set_seed)
set_seed_button.pack()

# Добавление кнопок для перемещения
move_buttons_frame = tk.Frame(root)
move_buttons_frame.pack()

left_button = tk.Button(move_buttons_frame, text="Left", command=move_left)
left_button.grid(row=0, column=0)

right_button = tk.Button(move_buttons_frame, text="Right", command=move_right)
right_button.grid(row=0, column=2)

up_button = tk.Button(move_buttons_frame, text="Up", command=move_up)
up_button.grid(row=1, column=1)

down_button = tk.Button(move_buttons_frame, text="Down", command=move_down)
down_button.grid(row=2, column=1)

# Запуск основного цикла интерфейса
root.mainloop()

Ссылка на гитхаб.

Последний раз редактировалось MakarovDs; 04.02.2025 в 19:20.
MakarovDs на форуме Ответить с цитированием
Старый 04.02.2025, 22:38   #47
MakarovDs
Форумчанин
 
Аватар для MakarovDs
 
Регистрация: 10.01.2020
Сообщений: 350
По умолчанию

В шестой версии я добавил поле ввода изменения скорости,и саму кнопку авторандома при нажатие на которую происходит автоматическое случайное переключение на случайную координату.

Код:
import tkinter as tk
import numpy as np
from PIL import Image, ImageTk
import pygame
import threading
import random
import time

# Инициализация Pygame
pygame.mixer.init()

# Параметры
video_window = None
canvas = None

# Начальные координаты и сид
x, y, z = 0, 0, 0
seed = 42
auto_random_running = False  # Переменная для отслеживания состояния авторандома
auto_random_thread = None  # Поток для авторандома
auto_random_delay = 1  # Задержка по умолчанию 1 секунда

def generate_random_audio(sample_rate=44100, duration=1):
    audio_data = np.random.uniform(-1, 1, int(sample_rate * duration)).astype(np.float32)
    return audio_data

def generate_random_video(seed, width=640, height=480):
    np.random.seed(seed)
    return np.random.randint(0, 256, (height, width, 3), dtype=np.uint8)

def play_sound():
    sample_rate = 44100
    while True:
        sound = generate_random_audio(sample_rate)
        sound = (sound * 32767).astype(np.int16)
        pygame.mixer.Sound(buffer=sound.tobytes()).play()
        pygame.time.delay(100)

def display_video():
    global video_window, canvas
    video_window = tk.Toplevel()
    video_window.title("Random Video")

    canvas = tk.Canvas(video_window, width=640, height=480)
    canvas.pack()

    update_frame()  # Первый кадр

def start_audio_and_video():
    thread = threading.Thread(target=play_sound, daemon=True)
    thread.start()
    display_video()

def update_frame():
    if canvas:
        # Генерация нового сида на основе координат и текущего сида из поля
        current_seed = (x * 10000 + y * 100 + z + seed) % (2**32)
        frame = generate_random_video(current_seed)  # Генерация нового кадра с использованием сида
        frame_image = Image.fromarray(frame)
        frame_image = ImageTk.PhotoImage(frame_image)

        # Обновление Canvas
        canvas.delete('all')
        canvas.create_image(0, 0, anchor=tk.NW, image=frame_image)
        canvas.image = frame_image  # Сохраняем ссылку для предотвращения сборки мусора

def update_coordinates_display():
    coordinates_label.config(text=f"Координаты - x: {x}, y: {y}, z: {z}, Seed: {seed}")

def move_left():
    global x
    x -= 1
    update_frame()
    update_coordinates_display()

def move_right():
    global x
    x += 1
    update_frame()
    update_coordinates_display()

def move_up():
    global y
    y += 1
    update_frame()
    update_coordinates_display()

def move_down():
    global y
    y -= 1
    update_frame()
    update_coordinates_display()

def set_seed():
    global seed
    try:
        seed = int(seed_entry.get())
        update_frame()  # Обновление кадра с новым сидом
        update_coordinates_display()  # Обновление отображения координат
    except ValueError:
        seed_entry.delete(0, tk.END)
        seed_entry.insert(0, str(seed))  # Восстановление введённого значения, если ввод некорректен

def validate_seed_input(event):
    current_value = seed_entry.get()
    if not current_value.isdigit():
        seed_entry.delete(0, tk.END)
        seed_entry.insert(0, ''.join(filter(str.isdigit, current_value)))  # Удалить некорректные символы

def toggle_auto_random():
    global auto_random_running, auto_random_thread
    if auto_random_running:
        auto_random_running = False
        if auto_random_thread is not None:
            auto_random_thread.join()  # Дождаться завершения потока
        auto_random_button.config(text="Запустить авторандом")
    else:
        auto_random_running = True
        auto_random_button.config(text="Остановить авторандом")
        auto_random_thread = threading.Thread(target=auto_random_coordinates)
        auto_random_thread.start()

def auto_random_coordinates():
    global x, y, z, auto_random_delay
    while auto_random_running:
        x = random.randint(0, 10000)
        y = random.randint(0, 10000)
        z = random.randint(0, 10000)
        update_frame()
        update_coordinates_display()
        time.sleep(auto_random_delay)  # Задержка между обновлениями

def set_auto_random_delay():
    global auto_random_delay
    try:
        delay = float(auto_random_delay_entry.get())
        if delay > 0:  # Убедимся, что задержка положительная
            auto_random_delay = delay
    except ValueError:
        auto_random_delay_entry.delete(0, tk.END)
        auto_random_delay_entry.insert(0, str(auto_random_delay))  # Восстановление значения, если ввод некорректен

# Создание основного окна
root = tk.Tk()
root.title("Procedural Audio and Video")
root.geometry("320x250")

start_button = tk.Button(root, text="Start", command=start_audio_and_video)
start_button.pack()

coordinates_label = tk.Label(root, text=f"Координаты - x: {x}, y: {y}, z: {z}, Seed: {seed}")
coordinates_label.pack()

seed_entry = tk.Entry(root)
seed_entry.pack()
seed_entry.insert(0, str(seed))  # Ввод сида по умолчанию

seed_entry.bind('<KeyRelease>', validate_seed_input)  # Проверка ввода сида

set_seed_button = tk.Button(root, text="Установить сид", command=set_seed)
set_seed_button.pack()

# Поле ввода для изменения скорости переключения
auto_random_delay_entry = tk.Entry(root)
auto_random_delay_entry.pack()
auto_random_delay_entry.insert(0, str(auto_random_delay))  # Ввод задержки по умолчанию

set_delay_button = tk.Button(root, text="Установить задержку", command=set_auto_random_delay)
set_delay_button.pack()

# Добавление кнопок для перемещения
move_buttons_frame = tk.Frame(root)
move_buttons_frame.pack()

left_button = tk.Button(move_buttons_frame, text="Left", command=move_left)
left_button.grid(row=0, column=0)

right_button = tk.Button(move_buttons_frame, text="Right", command=move_right)
right_button.grid(row=0, column=2)

up_button = tk.Button(move_buttons_frame, text="Up", command=move_up)
up_button.grid(row=1, column=1)

down_button = tk.Button(move_buttons_frame, text="Down", command=move_down)
down_button.grid(row=2, column=1)

# Кнопка для авторандома
auto_random_button = tk.Button(root, text="Запустить авторандом", command=toggle_auto_random)
auto_random_button.pack()

# Запуск основного цикла интерфейса
root.mainloop()
Ссылка на гитхаб.

MakarovDs на форуме Ответить с цитированием
Старый 09.02.2025, 13:57   #48
MakarovDs
Форумчанин
 
Аватар для MakarovDs
 
Регистрация: 10.01.2020
Сообщений: 350
По умолчанию

Короче я решил вернуться к старому мозаичному генератору из 42 комментария, и сделать такую версию что-бы перемешивались все пиксели в картинке которую мы выбрали.
Код:
import tkinter as tk
import numpy as np
from PIL import Image, ImageTk
import random
import time
from tkinter import filedialog

# Параметры
image_data = None  # Хранение данных изображения
mosaic_arrays = []  # Массив мозаик
canvas = None  # Canvas для отображения изображения

# Функция для загрузки изображений
def load_image():
    global image_data, canvas
    file_path = filedialog.askopenfilename()
    if file_path:
        image = Image.open(file_path).convert("RGB")
        image_data = np.array(image)  # Сохранение данных изображения как массива
        generate_mosaics(image_data)  # Генерация мозайки из загруженного изображения

def generate_mosaics(image):
    global mosaic_arrays
    height, width, _ = image.shape
    mosaic_arrays = []
    remaining_pixels = height * width

    # Пример объединений в мозаики
    while remaining_pixels > 0:
        # Генерация случайного числа для количества пикселей в мозаике
        num_pixels = random.randint(1, remaining_pixels)  
        mosaic = []

        for _ in range(num_pixels):
            if remaining_pixels > 0:
                x_coord = random.randint(0, height - 1)
                y_coord = random.randint(0, width - 1)
                mosaic.append(image[x_coord, y_coord])  # Добавляем цвет пикселя в мозаику
                remaining_pixels -= 1
        
        mosaic_arrays.append(mosaic)

    random.shuffle(mosaic_arrays)  # Перемешивание мозайки

    # Преобразование мозайки в массив
    flat_mosaic = [color for mosaic in mosaic_arrays for color in mosaic]

    # Отображение результирующей мозайки
    update_canvas(flat_mosaic, width)

def update_canvas(flat_mosaic, width):
    """Отображает мозаику на Canvas."""
    global canvas
    if canvas is None:
        # Создаем новое окно для отображения
        canvas_window = tk.Toplevel()
        canvas = tk.Canvas(canvas_window, width=640, height=480)
        canvas.pack()

    mosaic_image = np.array(flat_mosaic).reshape((-1, width, 3))  # Формируем изображение из массива
    mosaic_image = Image.fromarray(np.uint8(mosaic_image))

    # Отображение изображения мозайки в Canvas
    mosaic_image_tk = ImageTk.PhotoImage(mosaic_image)
    canvas.delete('all')
    canvas.create_image(0, 0, anchor=tk.NW, image=mosaic_image_tk)
    canvas.image = mosaic_image_tk  # Сохраняем ссылку для предотвращения сборки мусора

# Создание основного окна
root = tk.Tk()
root.title("Procedural Mosaic Generator")
root.geometry("320x250")

# Кнопка для загрузки изображения
load_image_button = tk.Button(root, text="Загрузить изображение", command=load_image)
load_image_button.pack()

# Запуск основного цикла интерфейса
root.mainloop()
Рублённая щепка пикселей.

Ссылка на гитхаб -> мозаичный пиксельный генератор версия 1.

Последний раз редактировалось MakarovDs; 09.02.2025 в 18:16.
MakarovDs на форуме Ответить с цитированием
Старый 09.02.2025, 15:40   #49
MakarovDs
Форумчанин
 
Аватар для MakarovDs
 
Регистрация: 10.01.2020
Сообщений: 350
По умолчанию

Но мне нужно не картинка а видео.
Код:
import tkinter as tk
import numpy as np
from PIL import Image, ImageTk
import random
from tkinter import filedialog
import os

# Параметры
image_data = None  # Хранение данных изображения
mosaic_arrays = []  # Массив мозаик
canvas = None  # Canvas для отображения
current_flat_mosaic = None  # Хранить текущую плоскую мозаику для сохранения
update_interval = 1000  # Интервал обновления в миллисекундах (1000 мс = 1 секунда)

def load_image():
    global image_data, current_flat_mosaic
    file_path = filedialog.askopenfilename()
    if file_path:
        image = Image.open(file_path).convert("RGB")
        image_data = np.array(image)  # Сохранение данных изображения как массива
        current_flat_mosaic = generate_mosaics(image_data)  # Генерация мозаики из загруженного изображения
        update_canvas(current_flat_mosaic, image_data.shape[1])  # Обновляем canvas с начальной мозаикой
        update_mosaic()  # Начинаем обновление мозаики

def generate_mosaics(image):
    global mosaic_arrays
    height, width, _ = image.shape
    mosaic_arrays = []
    remaining_pixels = height * width

    # Генерация мозайки
    while remaining_pixels > 0:
        num_pixels = random.randint(1, remaining_pixels)  
        mosaic = []

        for _ in range(num_pixels):
            if remaining_pixels > 0:
                x_coord = random.randint(0, height - 1)
                y_coord = random.randint(0, width - 1)
                mosaic.append(image[x_coord, y_coord])  # Добавляем цвет пикселя в мозаику
                remaining_pixels -= 1
        
        mosaic_arrays.append(mosaic)

    random.shuffle(mosaic_arrays)  # Перемешивание мозайки

    # Преобразование мозаики в массив
    flat_mosaic = [color for mosaic in mosaic_arrays for color in mosaic]
    
    return flat_mosaic  # Возвращаем плоскую мозаику для дальнейшего использования

def update_canvas(flat_mosaic, width):
    """Отображает мозаику на Canvas."""
    global canvas
    if canvas is None:
        # Создаем новое окно для отображения
        canvas_window = tk.Toplevel()
        canvas = tk.Canvas(canvas_window, width=640, height=480)
        canvas.pack()

    mosaic_image = np.array(flat_mosaic).reshape((-1, width, 3))  # Формируем изображение из массива
    mosaic_image = Image.fromarray(np.uint8(mosaic_image))

    # Отображение изображения мозайки в Canvas
    mosaic_image_tk = ImageTk.PhotoImage(mosaic_image)
    canvas.delete('all')
    canvas.create_image(0, 0, anchor=tk.NW, image=mosaic_image_tk)
    canvas.image = mosaic_image_tk  # Сохраняем ссылку для предотвращения сборки мусора

def update_mosaic():
    global image_data, current_flat_mosaic
    if image_data is not None:
        current_flat_mosaic = generate_mosaics(image_data)  # Генерация новой мозаики
        update_canvas(current_flat_mosaic, image_data.shape[1])  # Обновляем canvas
    root.after(update_interval, update_mosaic)  # Запланировать следующую перезагрузку

def save_image():
    global current_flat_mosaic
    if current_flat_mosaic is not None:
        desktop_path = os.path.join(os.path.expanduser("~"), "Desktop")
        save_path = os.path.join(desktop_path, "mosaic_image.png")

        # Определяем количество пикселей
        num_pixels = len(current_flat_mosaic) // 3

        # Убедимся, что количество пикселей делится на 3
        if len(current_flat_mosaic) % 3 != 0:
            print("Ошибка: размер мозаики не кратен 3.")
            return

        # Вычисляем размер для ресайза
        width = int(np.sqrt(num_pixels))  # Примерная ширина
        height = num_pixels // width  # Высота

        # Если кто-то (например, ширина) не может быть равным нулю, используем максимально возможный размер
        if width * height < num_pixels:
            height += 1
        
        mosaic_image = np.array(current_flat_mosaic).reshape((height, width, 3))  # Формируем изображение
        mosaic_image = Image.fromarray(np.uint8(mosaic_image))
        mosaic_image.save(save_path)  # Сохранение изображения на рабочий стол
        print(f"Изображение сохранено по: {save_path}")

# Создание основного окна
root = tk.Tk()
root.title("Procedural Mosaic Generator")
root.geometry("320x250")

# Кнопка для загрузки изображения
load_image_button = tk.Button(root, text="Загрузить изображение", command=load_image)
load_image_button.pack()

# Кнопка для сохранения изображения
save_image_button = tk.Button(root, text="Сохранить мозаику", command=save_image)
save_image_button.pack()

# Запуск основного цикла интерфейса
root.mainloop()
Вот что получается

Ссылка на гитхаб - > мозаичный пиксельный генератор версия 2.

Последний раз редактировалось MakarovDs; 09.02.2025 в 18:16.
MakarovDs на форуме Ответить с цитированием
Старый 09.02.2025, 16:32   #50
MakarovDs
Форумчанин
 
Аватар для MakarovDs
 
Регистрация: 10.01.2020
Сообщений: 350
По умолчанию

Теперь нужно сделать это с множеством изображений:
Код:
import tkinter as tk
from tkinter import filedialog, messagebox
import numpy as np
from PIL import Image, ImageTk
import random
import os

# Параметры
image_data = []  # Хранение данных изображений
canvas = None  # Canvas для отображения
current_flat_mosaic = None  # Хранить текущую плоскую мозаику для сохранения
canvas_width = 640  # Ширина холста
canvas_height = 480  # Высота холста
update_interval = 100  # Интервал обновления в миллисекундах
iterations = 10  # Количество итераций (10 обновлений за 1 секунду)

def load_images():
    global image_data
    file_paths = filedialog.askopenfilenames(filetypes=[("Image files", "*.jpg;*.png;*.jpeg")])
    if file_paths:
        for fp in file_paths:
            img = Image.open(fp)
            img = img.resize((canvas_width, canvas_height))  # Устанавливаем фиксированный размер
            image_data.append(np.array(img.convert("RGB")))
            image_listbox.insert(tk.END, fp)  # Добавление каждого пути к списку (отображение на новой строке)

def generate_random_mosaic(images):
    if len(images) < 1:
        return np.zeros((canvas_height, canvas_width, 3), dtype=np.uint8)  # Возвращаем пустое изображение
    
    flat_mosaic = []
    total_pixels = canvas_width * canvas_height

    for _ in range(total_pixels):
        idx = random.randint(0, len(images) - 1)  # Случайный индекс изображения
        img_pixels = images[idx].reshape(-1, 3)  # Преобразуем в одномерный массив пикселей
        random_pixel = random.choice(img_pixels)  # Случайный пиксель
        flat_mosaic.append(random_pixel)

    return np.array(flat_mosaic).reshape((canvas_height, canvas_width, 3))

def update_canvas(flat_mosaic):
    global canvas
    if canvas is None:
        canvas_window = tk.Toplevel()
        canvas = tk.Canvas(canvas_window, width=canvas_width, height=canvas_height)
        canvas.pack()

    mosaic_image = Image.fromarray(np.uint8(flat_mosaic))
    mosaic_image_tk = ImageTk.PhotoImage(mosaic_image)
    canvas.delete('all')
    canvas.create_image(0, 0, anchor=tk.NW, image=mosaic_image_tk)
    canvas.image = mosaic_image_tk

def start_mosaic():
    if image_data:
        run_mosaic_animation(iterations)  # Запускаем анимацию
    else:
        messagebox.showwarning("Предупреждение", "Сначала загрузите хотя бы одно изображение.")

def run_mosaic_animation(remaining_iterations):
    if remaining_iterations > 0:
        flat_mosaic = generate_random_mosaic(image_data)
        update_canvas(flat_mosaic)
        root.after(update_interval, run_mosaic_animation, remaining_iterations - 1)  # Запланировать следующую итерацию
    else:
        print("Воспроизведение завершено.")

def save_image():
    global current_flat_mosaic
    if current_flat_mosaic is not None and current_flat_mosaic.size > 0:
        desktop_path = os.path.join(os.path.expanduser("~"), "Desktop")
        save_path = os.path.join(desktop_path, "mosaic_image.png")
        mosaic_image = Image.fromarray(np.uint8(current_flat_mosaic))
        mosaic_image.save(save_path)
        print(f"Изображение сохранено по: {save_path}")

# Создание основного окна
root = tk.Tk()
root.title("Генератор мозаики")
root.geometry("400x500")

load_image_button = tk.Button(root, text="Загрузить изображения", command=load_images)
load_image_button.pack()

start_button = tk.Button(root, text="Запустить мозаику", command=start_mosaic)
start_button.pack()

save_image_button = tk.Button(root, text="Сохранить мозаику", command=save_image)
save_image_button.pack()

image_listbox = tk.Listbox(root, width=60, height=15)
image_listbox.pack()

root.mainloop()

Ссылка на гитхаб -> мозаичный пиксельный генератор версия 3.

Последний раз редактировалось MakarovDs; 09.02.2025 в 18:15.
MakarovDs на форуме Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Реализация симуляции банкомата A7A7A7 Общие вопросы C/C++ 0 15.09.2023 23:48
Технологии симуляции жизни в играх Человек_Борща Свободное общение 6 22.11.2013 14:59
Создание большого 3D мира ardor Gamedev - cоздание игр: Unity, OpenGL, DirectX 4 02.03.2012 00:14
Создание катры мира (от Яндекса) с помощью Дельфи Alex Cones Общие вопросы Delphi 2 27.05.2009 09:16
Компьютерное моделирование. Создание модели движения тел по определенной траектории. AnaVare Помощь студентам 7 18.03.2009 05:09