analitics

Pages

Wednesday, July 2, 2025

Python Qt6 : ... simple resize image files.

I like the combination of Python development and the inclusion of the PyQt6 module. It is very fast and stable and allows me to create all sorts of tools to use.
Today I will show you another handy script that allows you to read all the image files from a folder and, depending on the selections: height, length, and/or aspect ratio, resize them and then place them in a folder created specifically for the resulting images.
Here is how the script looks, I clearly used artificial intelligence and it didn't take more than a few minutes, my evaluation, testing, and rearranging the interface took longer ...
import sys
import os
from datetime import datetime
from PyQt6.QtWidgets import QApplication, QMainWindow, QWidget, QVBoxLayout, QPushButton, QFileDialog, QLineEdit, QCheckBox, QLabel, QMessageBox
from PyQt6.QtCore import Qt
from PIL import Image

class ResizeApp(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Image Resizer")
        self.setGeometry(100, 100, 400, 200)

        layout = QVBoxLayout()
        central_widget = QWidget()
        central_widget.setLayout(layout)
        self.setCentralWidget(central_widget)

        self.folder_button = QPushButton("Select Folder")
        self.folder_button.clicked.connect(self.select_folder)
        layout.addWidget(self.folder_button)

        self.width_edit = QLineEdit("800")
        self.width_edit.setPlaceholderText("Width (px)")
        layout.addWidget(QLabel("Width:"))
        layout.addWidget(self.width_edit)

        self.height_edit = QLineEdit("600")
        self.height_edit.setPlaceholderText("Height (px)")
        layout.addWidget(QLabel("Height:"))
        layout.addWidget(self.height_edit)

        self.aspect_ratio = QCheckBox("Maintain Aspect Ratio")
        self.aspect_ratio.setChecked(True)
        layout.addWidget(self.aspect_ratio)

        self.resize_button = QPushButton("Resize Images")
        self.resize_button.clicked.connect(self.resize_images)
        layout.addWidget(self.resize_button)

        self.folder_path = ""

    def select_folder(self):
        self.folder_path = QFileDialog.getExistingDirectory(self, "Select Image Folder")
        if self.folder_path:
            self.folder_button.setText(f"Selected: {os.path.basename(self.folder_path)}")

    def resize_images(self):
        if not self.folder_path:
            QMessageBox.warning(self, "Error", "Please select a folder.")
            return

        try:
            width = int(self.width_edit.text())
            height = int(self.height_edit.text())
        except ValueError:
            QMessageBox.warning(self, "Error", "Please enter valid width and height.")
            return

        if width <= 0 or height <= 0:
            QMessageBox.warning(self, "Error", "Width and height must be positive.")
            return

        date_str = datetime.now().strftime("%d%m%y_%H%M")
        aspect_str = "asp_on" if self.aspect_ratio.isChecked() else "asp_off"
        output_folder = os.path.join(self.folder_path, f"resized_{date_str}_{height}_{aspect_str}")
        os.makedirs(output_folder, exist_ok=True)

        for file_name in os.listdir(self.folder_path):
            if file_name.lower().endswith(('.png', '.jpg', '.jpeg', '.bmp', '.gif')):
                image_path = os.path.join(self.folder_path, file_name)
                try:
                    with Image.open(image_path) as img:
                        if self.aspect_ratio.isChecked():
                            img.thumbnail((width, height), Image.Resampling.LANCZOS)
                        else:
                            img = img.resize((width, height), Image.Resampling.LANCZOS)
                        output_path = os.path.join(output_folder, f"resized_{date_str}_{height}_{aspect_str}_{file_name}")
                        img.save(output_path)
                except Exception as e:
                    QMessageBox.warning(self, "Error", f"Failed to process {file_name}: {str(e)}")

        QMessageBox.information(self, "Success", f"Images resized and saved to {output_folder}!")

if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = ResizeApp()
    window.show()
    sys.exit(app.exec())

Tuesday, July 1, 2025

Python 3.13.5 : use the jupyterlab, notebook and voila - part 001.

JupyterLab is the latest web-based interactive development environment for notebooks, code, and data. Its flexible interface allows users to configure and arrange workflows in data science, scientific computing, computational journalism, and machine learning. A modular design invites extensions to expand and enrich functionality.
Let's test with these python modules: jupyterlab, notebook and voila.
First, I install with pip tool the jupyterlab python module:
pip install jupyterlab
Collecting jupyterlab
...
Successfully installed anyio-4.9.0 argon2-cffi-25.1.0 argon2-cffi-bindings-21.2.0 arrow-1.3.0 asttokens-3.0.0 async-lru-2.0.5
attrs-25.3.0 babel-2.17.0 bleach-6.2.0 cffi-1.17.1 comm-0.2.2 debugpy-1.8.14 defusedxml-0.7.1 executing-2.2.0 
fastjsonschema-2.21.1 fqdn-1.5.1 h11-0.16.0 httpcore-1.0.9 httpx-0.28.1 ipykernel-6.29.5 ipython-9.4.0 
ipython-pygments-lexers-1.1.1 isoduration-20.11.0 jedi-0.19.2 json5-0.12.0 jsonpointer-3.0.0 jsonschema-4.24.0 
jsonschema-specifications-2025.4.1 jupyter-client-8.6.3 jupyter-core-5.8.1 jupyter-events-0.12.0 jupyter-lsp-2.2.5 
jupyter-server-2.16.0 jupyter-server-terminals-0.5.3 jupyterlab-4.4.4 jupyterlab-pygments-0.3.0 jupyterlab-server-2.27.3 
matplotlib-inline-0.1.7 mistune-3.1.3 nbclient-0.10.2 nbconvert-7.16.6 nbformat-5.10.4 nest-asyncio-1.6.0 notebook-shim-0.2.4
overrides-7.7.0 pandocfilters-1.5.1 parso-0.8.4 platformdirs-4.3.8 prometheus-client-0.22.1 prompt_toolkit-3.0.51 
psutil-7.0.0 pure-eval-0.2.3 pycparser-2.22 python-json-logger-3.3.0 pywin32-310 pywinpty-2.0.15 pyyaml-6.0.2 pyzmq-27.0.0
referencing-0.36.2 rfc3339-validator-0.1.4 rfc3986-validator-0.1.1 rpds-py-0.26.0 send2trash-1.8.3 sniffio-1.3.1 
stack_data-0.6.3 terminado-0.18.1 tinycss2-1.4.0 tornado-6.5.1 traitlets-5.14.3 types-python-dateutil-2.9.0.20250516 
uri-template-1.3.0 wcwidth-0.2.13 webcolors-24.11.1 webencodings-0.5.1 websocket-client-1.8.0
Next, the install of the notebook python module
pip install notebook
Collecting notebook
...
Installing collected packages: notebook
Successfully installed notebook-7.4.4
This python package named voila will help us to use online graphic user interfaces:
pip install voila
Collecting voila
...
Successfully installed voila-0.5.8 websockets-15.0.1
The voila package need to work with ipywidgets python package:
pip install ipywidgets
Collecting ipywidgets
...
Successfully installed ipywidgets-8.1.7 jupyterlab_widgets-3.0.15 widgetsnbextension-4.0.14
Let's start the jupiter tool with this command:
jupyter notebook
I used an default python example with a slider:
import ipywidgets as widgets
from IPython.display import display

slider = widgets.IntSlider(value=5, min=0, max=10)
display(slider)
This command will start the web with the slider using the voila command:
voila test.ipynb
The result is this:

Friday, June 27, 2025

Python 3.13.5 : the manim python module - part 001.

I used this package few days ago and now I wrote about how can used it.
Update the new release of pip is available: 25.0.1 -> 25.1.1 , run this command:
python.exe -m pip install --upgrade pip
The documentation can be found on the official website.
pip install manim
Collecting manim
  Downloading manim-0.19.0-py3-none-any.whl.metadata (11 kB)
...
Successfully installed Pillow-11.2.1 Pygments-2.19.1 audioop-lts-0.2.1 av-13.1.0 beautifulsoup4-4.13.4 click-8.2.1 cloup-3.0.7 colorama-0.4.6 decorator-5.2.1 glcontext-3.0.0 isosurfaces-0.1.2 manim-0.19.0 manimpango-0.6.0 mapbox-earcut-1.0.3 markdown-it-py-3.0.0 mdurl-0.1.2 moderngl-5.12.0 moderngl-window-3.1.1 networkx-3.5 numpy-2.3.0 pycairo-1.28.0 pydub-0.25.1 pyglet-2.1.6 pyglm-2.8.2 rich-14.0.0 scipy-1.15.3 screeninfo-0.8.1 skia-pathops-0.8.0.post2 soupsieve-2.7 srt-3.5.3 svgelements-1.9.6 tqdm-4.67.1 typing-extensions-4.14.0 watchdog-6.0.0
Let's see how can be used to see the help area:
python.exe -m manim render --help
Manim Community v0.19.0

Usage: python -m manim render ...
Let's use this source code:
from manim import *

class AdvancedAnimation(Scene):
    def construct(self):
        # Scene 1: Introduction
        title = Text("Advanced Animation with Manim").scale(0.76)
        self.play(FadeIn(title))
        self.wait(2)

        # Scene 2: Custom Animation
        circle = Circle().set_fill(color=BLUE, opacity=0.5)
        square = Square().set_fill(color=RED, opacity=0.5)
        self.add(circle, square)
        self.play(
            Rotate(circle, angle=TAU),
            Rotate(square, angle=-TAU),
            run_time=2,
            rate_func=linear
        )
        self.wait()

        # Scene 3: Text Animation
        text = Text("This is a custom text animation", font_size=40).to_edge(UP)
        self.play(Write(text), run_time=2)
        self.wait()

        # Scene 4: Shapes Manipulation
        triangle = Triangle().shift(RIGHT * 2)
        self.play(GrowFromCenter(triangle), run_time=1.5)
        self.wait()

        # Scene 5: Transition to next scene
        self.play(Uncreate(triangle), FadeOut(text))

        # Scene 6: Final Animation
        final_text = Text("This is the end of our animation", font_size=50).to_edge(DOWN)
        self.play(FadeIn(final_text), run_time=1.5)
        self.wait(2)

# Run the animation
AdvancedAnimation()
Use this command to render:
python.exe -m manim render manim_test_001.py AdvancedAnimation -p
AdvancedAnimation -p
Manim Community v0.19.0

[06/27/25 19:52:43] INFO     Animation 0 : Partial movie file      scene_file_writer.py:588
                             written in
                             'D:\PythonProjects\manim_projects\med
                             ia\videos\manim_test_001\1080p60\part
                             ial_movie_files\AdvancedAnimation\397
                             7891868_355746014_223132457.mp4'
...
[06/27/25 19:53:56] INFO     Previewed File at:                             file_ops.py:237
                             'D:\PythonProjects\manim_projects\media\videos
                             \manim_test_001\1080p60\AdvancedAnimation.mp4'
The result comes with many files, see this 1080p60 video result:

Python Qt6 : ... simple processing file.

Today I will show you an simple python script with PyQt6.
This script ai build using the artificial inteligence and I tested will process your files by slections : copy to another folder , zip all selected and delete all selected.
import sys
import os
import re
import shutil
import zipfile
from PyQt6.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, 
                            QPushButton, QListWidget, QFileDialog, QMessageBox, QDialog, QLabel)
from PyQt6.QtCore import Qt

class CriteriaDialog(QDialog):
    def __init__(self, folder, parent=None):
        super().__init__(parent)
        self.setWindowTitle(f"Processing Folder: {folder}")
        self.layout = QVBoxLayout(self)
        self.layout.addWidget(QLabel(f"Selected folder: {folder}"))
        self.ok_button = QPushButton("OK")
        self.ok_button.clicked.connect(self.accept)
        self.layout.addWidget(self.ok_button)

class DuplicateFinder(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Duplicate File Finder")
        self.setGeometry(100, 100, 600, 400)
        
        self.central_widget = QWidget()
        self.setCentralWidget(self.central_widget)
        self.layout = QVBoxLayout(self.central_widget)
        
        self.file_list = QListWidget()
        self.file_list.setSelectionMode(QListWidget.SelectionMode.MultiSelection)
        self.layout.addWidget(self.file_list)
        
        button_layout = QHBoxLayout()
        self.select_button = QPushButton("Select Folder")
        self.select_button.clicked.connect(self.select_folder)
        button_layout.addWidget(self.select_button)
        
        self.copy_button = QPushButton("Copy To")
        self.copy_button.clicked.connect(self.copy_files)
        button_layout.addWidget(self.copy_button)
        
        self.zip_button = QPushButton("Zip All")
        self.zip_button.clicked.connect(self.zip_files)
        button_layout.addWidget(self.zip_button)
        
        self.delete_button = QPushButton("Delete All")
        self.delete_button.clicked.connect(self.delete_files)
        button_layout.addWidget(self.delete_button)
        
        self.layout.addLayout(button_layout)
        
        self.files = []
        self.selected_folder = ""
        
    def select_folder(self):
        folder = QFileDialog.getExistingDirectory(self, "Select Folder")
        if folder:
            self.selected_folder = folder
            dialog = CriteriaDialog(folder, self)
            if dialog.exec():
                self.files = []
                self.file_list.clear()
                self.scan_folder(folder)
                self.find_duplicates()
            
    def scan_folder(self, folder):
        for root, _, files in os.walk(folder):
            for file in files:
                file_path = os.path.join(root, file)
                self.files.append({
                    'path': file_path,
                    'name': os.path.basename(file_path),
                    'size': os.path.getsize(file_path),
                    'extension': os.path.splitext(file_path)[1]
                })
                
    def find_duplicates(self):
        duplicates = self.find_by_similar_name()
        self.display_duplicates(duplicates)
        
    def find_by_similar_name(self):
        duplicates = []
        name_groups = {}
        pattern = r'(.+?)(?:[\s_-]*\d{3,}|[\s_-]*\d{1,2}|_)?(?:\.\w+)?$'
        
        for file in self.files:
            match = re.match(pattern, file['name'])
            if match:
                base_name = match.group(1)
                if base_name in name_groups:
                    name_groups[base_name].append(file)
                else:
                    name_groups[base_name] = [file]
        
        for base_name, files in name_groups.items():
            if len(files) > 1:
                duplicates.extend(files)
                
        return duplicates
    
    def display_duplicates(self, duplicates):
        self.file_list.clear()
        for file in duplicates:
            self.file_list.addItem(file['path'])
            
    def copy_files(self):
        if not self.file_list.selectedItems():
            QMessageBox.warning(self, "Warning", "No files selected!")
            return
        dest_folder = QFileDialog.getExistingDirectory(self, "Select Destination Folder")
        if dest_folder:
            for item in self.file_list.selectedItems():
                file_path = item.text()
                dest_path = os.path.join(dest_folder, os.path.basename(file_path))
                shutil.copy2(file_path, dest_path)
            QMessageBox.information(self, "Success", "Files copied!")
            
    def zip_files(self):
        if not self.file_list.selectedItems():
            QMessageBox.warning(self, "Warning", "No files selected!")
            return
        zip_path = QFileDialog.getSaveFileName(self, "Save Zip File", "", "Zip Files (*.zip)")[0]
        if zip_path:
            with zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) as zipf:
                for item in self.file_list.selectedItems():
                    file_path = item.text()
                    zipf.write(file_path, os.path.basename(file_path))
            QMessageBox.information(self, "Success", "Files zipped!")
        
    def delete_files(self):
        if not self.file_list.selectedItems():
            QMessageBox.warning(self, "Warning", "No files selected!")
            return
        reply = QMessageBox.question(self, "Confirm", "Delete selected files?",
                                  QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No)
        if reply == QMessageBox.StandardButton.Yes:
            for item in self.file_list.selectedItems():
                os.remove(item.text())
            self.file_list.clear()
            QMessageBox.information(self, "Success", "Files deleted!")

if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = DuplicateFinder()
    window.show()
    sys.exit(app.exec())

Tuesday, June 24, 2025

Python 3.13.5 : Get bookmarks from Edge browser with python.

Today I tested with these python modules json and pathlib.
This python script will get all bookmarks from Edge browser:
import json
from pathlib import Path

bookmark_path = Path.home() / "AppData/Local/Microsoft/Edge/User Data/Default/Bookmarks"

with open(bookmark_path, "r", encoding="utf-8") as f:
    data = json.load(f)

# Exemplu: listăm toate titlurile bookmark-urilor
def extract_bookmarks(bookmark_node):
    bookmarks = []
    if "children" in bookmark_node:
        for child in bookmark_node["children"]:
            bookmarks.extend(extract_bookmarks(child))
    elif bookmark_node.get("type") == "url":
        bookmarks.append((bookmark_node["name"], bookmark_node["url"]))
    return bookmarks

all_bookmarks = extract_bookmarks(data["roots"]["bookmark_bar"])
for name, url in all_bookmarks:
    print(f"{name}: {url}")

Friday, June 20, 2025

Python 3.13.5 : testing with flask, request and playwright python module.

Today some testing with these python modules: flask, request and playwright.
I used pip to install flask python package:
pip install flask
Collecting flask
  Downloading flask-3.1.1-py3-none-any.whl.metadata (3.0 kB)
...
Installing collected packages: markupsafe, itsdangerous, blinker, werkzeug, jinja2, flask
Successfully installed blinker-1.9.0 flask-3.1.1 itsdangerous-2.2.0 jinja2-3.1.6 markupsafe-3.0.2 werkzeug-3.1.3
pip install requests
...
Installing collected packages: urllib3, idna, charset_normalizer, certifi, requests
Successfully installed certifi-2025.6.15 charset_normalizer-3.4.2 idna-3.10 requests-2.32.4 urllib3-2.5.0
pip install playwright
Collecting playwright
...
Installing collected packages: pyee, greenlet, playwright
Successfully installed greenlet-3.2.3 playwright-1.52.0 pyee-13.0.0
...
playwright install
Downloading Chromium 136.0.7103.25 ...
This will download a lot fo files and the will install the playwright tool.
First script is simple one will try to get cloudflare header on default ip:
from flask import Flask, request

app = Flask(__name__)

@app.route("/")
def detecteaza_ipuri():
    ip_client = request.headers.get('CF-Connecting-IP', 'Necunoscut')
    ip_cloudflare = request.remote_addr
    return (
        f"IP real vizitator: {ip_client}
" f"IP Cloudflare (vizibil de server): {ip_cloudflare}" ) if __name__ == "__main__": app.run(debug=True)
The next one will check more ...
from flask import Flask, request
import requests
import ipaddress

app = Flask(__name__)

def este_ip_cloudflare(ip):
    try:
        raspuns = requests.get("https://www.cloudflare.com/ips-v4")
        raspuns.raise_for_status()
        subneturi = raspuns.text.splitlines()

        for subnet in subneturi:
            if ipaddress.ip_address(ip) in ipaddress.ip_network(subnet):
                return True
        return False
    except Exception as e:
        return f"Eroare la verificarea IP-ului Cloudflare: {e}"

@app.route("/")
def detecteaza_ipuri():
    ip_client = request.headers.get('CF-Connecting-IP', 'Necunoscut')
    ip_cloudflare = request.remote_addr
    rezultat = este_ip_cloudflare(ip_cloudflare)

    return (
        f"IP real vizitator: {ip_client}
" f"IP Cloudflare (forwarder): {ip_cloudflare}
" f"Este IP-ul din rețeaua Cloudflare? {'DA' if rezultat == True else 'NU' if rezultat == False else rezultat}" ) if __name__ == "__main__": app.run(host="0.0.0.0", port=5000)
Now, the script with the request python module:
import requests

url = "https://cobalt.tools"
headers = {
    "User-Agent": "Mozilla/5.0",  # Simulează un browser real
}

try:
    r = requests.get(url, headers=headers, timeout=10)
    content = r.text.lower()

    print(f"Cod răspuns HTTP: {r.status_code}")

    if "cloudflare" in content or "cf-ray" in content or "attention required" in content:
        print("Cloudflare a intermediat cererea sau a blocat-o cu o pagină specială.")
    else:
        print("Cererea a fost servită normal.")
except Exception as e:
    print(f"Eroare la conexiune: {e}")
The last one will use the playwright python module:
import sys
import re
from urllib.parse import urlparse
from pathlib import Path
from playwright.sync_api import sync_playwright

def converteste_url_in_nume_fisier(url):
    parsed = urlparse(url)
    host = parsed.netloc.replace('.', '_')
    path = parsed.path.strip('/').replace('/', '_')
    if not path:
        path = 'index'
    return f"{host}_{path}.txt"

if len(sys.argv) != 2:
    print("Utilizare: python script.py https://exemplu.com")
    sys.exit(1)

url = sys.argv[1]
fisier_output = converteste_url_in_nume_fisier(url)

with sync_playwright() as p:
    browser = p.chromium.launch(headless=True)
    pagina = browser.new_page()
    pagina.goto(url, wait_until='networkidle')
    continut = pagina.content()
    Path(fisier_output).write_text(continut, encoding='utf-8')
    browser.close()

print(f"Conținutul a fost salvat în: {fisier_output}")
This will create a file with the source code of web page.

Thursday, June 19, 2025

News : UV - fast Python package and project manager.

An extremely fast Python package and project manager, written in Rust.
cd uv_projects

uv_projects>uv init hello-world
Initialized project `hello-world` at `D:\PythonProjects\uv_projects\hello-world`

uv_projects>cd hello-world

uv_projects\hello-world>uv run main.py
Using CPython 3.13.5 interpreter at: C:\Python3135\python.exe
Creating virtual environment at: .venv
Hello from hello-world!

Saturday, June 14, 2025

Python 3.11.11 : Colab simple tests with Protocol Buffers - part 053.

The .proto file definition serves as a blueprint or schema for defining the structure of your data in Protocol Buffers. It plays a crucial role in ensuring data consistency and enabling efficient serialization and deserialization across different programming languages and systems.
You can find all steps on my colab_google - the GitHub repo.

Sunday, June 8, 2025

News : Python-Fiddle online tool.

Python-Fiddle is an online Python playground where you can write, run, and share Python code directly from the browser without any need to install and maintain Python and packages on your computer. This platform was created make Python programming accessible to everyone and everywhere. We hope to make this a useful tool for learning, teaching, sharing, and collaborating on Python projects.
You can find this online tool on the official website.

Tuesday, May 20, 2025

Python : ... time-travel debugging project.

... ime-travel debugging, a technique that allows developers to "rewind" their code execution and inspect past states.
This is an old GitHub project from four years old.
  • Execution Recording – The debugger logs each step of execution, including variable states and function calls.
  • State Snapshots – It captures snapshots of memory at different points in execution.
  • Reverse Execution – Developers can step backward through the code to analyze previous states.
  • IDE Integration – Some tools integrate with VSCode and PyCharm for seamless debugging
This project is dependent on the following technologies:
  • Node.js / Express
  • Python 3
  • SQLite
  • better-sqlite3
  • Nearley.js / Moo.js
  • TypeScript
  • HTML5 Canvas
  • Webpack
  • gcc / automake
Unfortunately, the Time Traveling Debugger project has only been tested on OSX and Linux, and Windows support is not officially available

Sunday, May 18, 2025

Python 3.13.0 : bad management of python versions - need to fix into environment ...

I don't like how python management comes now, because some data god to \AppData\ and custom folder ... this will block some EXE because is not into environment ...
Will be more easy if the python team will make a management of all python on operating system area ... one reason is virtual environement , but this one python version of running ...
Can be better ? The management of python versions can be improved with simple user interface selection to manage all python versions and python modules, maybe a separate command shell more good thar python command on command shell, maybe a simple artificial intelligence just for user intercations and management of working ...
See this example , when I need to change to a lower version of python just to test some old python modules ...
Installing collected packages: tqdm, tifffile, scipy, rpds-py, platformdirs, opencv-python-headless, networkx, llvmlite, lazy-loader, imageio, attrs, scikit-image, referencing, pooch, numba, pymatting, jsonschema-specifications, jsonschema, rembg
   ----------------------------------------  0/19 [tqdm]  WARNING: The script tqdm.exe is installed in 'C:\Users\nicol\AppData\Roaming\Python\Python313\Scripts' which is not on PATH.
  Consider adding this directory to PATH or, if you prefer to suppress this warning, use --no-warn-script-location.
   -- -------------------------------------  1/19 [tifffile]  WARNING: The scripts lsm2bin.exe, tiff2fsspec.exe, tiffcomment.exe and tifffile.exe are installed in 'C:\Users\nicol\AppData\Roaming\Python\Python313\Scripts' which is not on PATH.
  Consider adding this directory to PATH or, if you prefer to suppress this warning, use --no-warn-script-location.
  WARNING: The scripts imageio_download_bin.exe and imageio_remove_bin.exe are installed in 'C:\Users\nicol\AppData\Roaming\Python\Python313\Scripts' which is not on PATH.
  Consider adding this directory to PATH or, if you prefer to suppress this warning, use --no-warn-script-location. ----------
   ----------------------------------- ---- 17/19 [jsonschema]  WARNING: The script jsonschema.exe is installed in 'C:\Users\nicol\AppData\Roaming\Python\Python313\Scripts' which is not on PATH.
  Consider adding this directory to PATH or, if you prefer to suppress this warning, use --no-warn-script-location.
   ----------------------------------- ---- 17/19 [jsonschema]  WARNING: The script rembg.exe is installed in 'C:\Users\nicol\AppData\Roaming\Python\Python313\Scripts' which is not on PATH.
  Consider adding this directory to PATH or, if you prefer to suppress this warning, use --no-warn-script-location.
Successfully installed attrs-25.3.0 imageio-2.37.0 jsonschema-4.23.0 jsonschema-specifications-2025.4.1 lazy-loader-0.4 llvmlite-0.44.0 networkx-3.4.2 numba-0.61.2 opencv-python-headless-4.11.0.86 platformdirs-4.3.8 pooch-1.8.2 pymatting-1.1.14 referencing-0.36.2 rembg-2.0.66 rpds-py-0.25.0 scikit-image-0.25.2 scipy-1.15.3 tifffile-2025.5.10 tqdm-4.67.1

D:\PythonProjects\PyQt6\catafest_images_viewer>python main_001_removebk.py
Traceback (most recent call last):
  File "D:\PythonProjects\PyQt6\catafest_images_viewer\main_001_removebk.py", line 4, in 
    from image_viewer import ImageViewer
  File "D:\PythonProjects\PyQt6\catafest_images_viewer\image_viewer.py", line 7, in 
    from qt_setup import Image, ContextMenu, ProcessDialog, ProcessingManager, ImageProcessor
  File "D:\PythonProjects\PyQt6\catafest_images_viewer\qt_setup.py", line 5, in 
    from processing import ProcessDialog, ProcessingManager, ImageProcessor
  File "D:\PythonProjects\PyQt6\catafest_images_viewer\processing.py", line 7, in 
    from rembg import remove
  File "C:\Users\nicol\AppData\Roaming\Python\Python313\site-packages\rembg\__init__.py", line 5, in 
    from .bg import remove
  File "C:\Users\nicol\AppData\Roaming\Python\Python313\site-packages\rembg\bg.py", line 7, in 
    import onnxruntime as ort
ModuleNotFoundError: No module named 'onnxruntime'

Sunday, May 11, 2025

Python Qt6 : simple animation with sprites.

Today I created with addon for Blender 3D and result is an image with sprites ...
I used that image with sprites and PyQt6 to animate my desktop screen, see the result:
This is the source code I used:
import sys
from PyQt6.QtWidgets import QApplication, QLabel, QWidget, QVBoxLayout, QMenu

# diff PyQt6 versus old PyQt
from PyQt6.QtGui import QAction

from PyQt6.QtGui import QPixmap, QIcon
from PyQt6.QtCore import QTimer, Qt

class AnimatedWindow(QWidget):
    def __init__(self):
        super().__init__()

        # set window
        self.setWindowFlags(Qt.WindowType.FramelessWindowHint | Qt.WindowType.WindowStaysOnTopHint)
        self.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground)

        # build layout 
        layout = QVBoxLayout()
        self.label = QLabel(self)
        layout.addWidget(self.label)
        self.setLayout(layout)

        # load sprite sheet from Camera_256px.png file name
        sprite_sheet = QPixmap("Camera_256px.png")  
        self.frame_width = sprite_sheet.width() // 11  # because I have 11 sprite on image
        self.sprites = [sprite_sheet.copy(i * self.frame_width, 0, self.frame_width, sprite_sheet.height()) for i in range(11)]
        self.current_frame = 0

        # 
        self.timer = QTimer()
        self.timer.timeout.connect(self.update_animation)
        self.timer.start(150)  # Schimbă frame-ul la fiecare 150 ms

        # 
        self.resize(self.frame_width, sprite_sheet.height())

        # left down on screen 
        screen = QApplication.primaryScreen().geometry()
        self.move(10, screen.height() - self.height() - 10)

    def update_animation(self):
        """Actualizează sprite-ul în QLabel"""
        self.label.setPixmap(self.sprites[self.current_frame])
        self.current_frame = (self.current_frame + 1) % len(self.sprites)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = AnimatedWindow()
    window.show()
    sys.exit(app.exec())

Thursday, May 8, 2025

Python 3.11.11 : Colab simple image to video with stabilityai - part 052.

Today, a simple test with artificial intelligence and stabilityai/stable-video-diffusion-img2vid-xt.
The result is not very good, but I believe the source code can be improved ...
pipe = StableVideoDiffusionPipeline.from_pretrained(
    'stabilityai/stable-video-diffusion-img2vid-xt',
    torch_dtype=torch.float16,
    variant='fp16'
)

pipe.enable_model_cpu_offload()
You can find the source code on my colab GitHUb projects - catafest_069.