Hong-Phuc Bui
2024-09-27 8a9933e4decb3b6a57b47b6409474bd476920c24
demo show image
3 files modified
7 files added
1 files deleted
747 ■■■■■ changed files
bit_op_numpy_example.py 41 ●●●●● patch | view | raw | blame | history
image-demo/README.md 20 ●●●●● patch | view | raw | blame | history
image-demo/pyproject.toml 19 ●●●●● patch | view | raw | blame | history
image-demo/src/imgdemo/__init__.py patch | view | raw | blame | history
image-demo/src/imgdemo/guimain.py 74 ●●●●● patch | view | raw | blame | history
image-demo/src/imgdemo/mainwindow.ui 107 ●●●●● patch | view | raw | blame | history
image-demo/src/imgdemo/ui_mainwindow.py 111 ●●●●● patch | view | raw | blame | history
num-int/src/numint/ui_mainwindow.py 251 ●●●●● patch | view | raw | blame | history
stundenplan/src/pygraph/graphdemo.py 18 ●●●● patch | view | raw | blame | history
stundenplan/src/pygraph/shortestpath.py 53 ●●●●● patch | view | raw | blame | history
stundenplan/tests/pygraph/shortestpath_tests.py 53 ●●●● patch | view | raw | blame | history
bit_op_numpy_example.py
New file
@@ -0,0 +1,41 @@
import numpy as np
def print_binary_pattern_32(x):
    pattern = bin(x)[2:].zfill(32)
    print(x, ':', pattern[0:8], pattern[9:16], pattern[17:24], pattern[25:], len(pattern))
def to32_np_fn(x: list[np.uint8,np.uint8,np.uint8,np.uint8]):
    y = np.left_shift(x, [np.uint32(0), np.uint32(8), np.uint32(16), np.uint32(24)])
    return y[0] | y[1] | y[2] | y[3]
def to32_bit_op(x: list[np.uint8,np.uint8,np.uint8,np.uint8]):
    # 1 0000_0000 0000_0000 0000_0000 0000_0000
    mask = (2**32) | (x[3] << 24) | (x[2] << 16) | (x[1] << 8) | (x[0])
    # remove the most significant bit
    return mask & (2**32-1)
def quaternary_8bit_to_unary_32bit(data, to32_fn):
    four_group = np.array(data, dtype=np.uint8).reshape((-1, 4))
    return np.array([to32_fn(x) for x in four_group])
if __name__ == '__main__':
    raw_data = [255,   0, 15, 170,
                0b101, 0b1100, 0b1001101, 0b1000_0000,
                9, 10, 11, 0b1000_0000]
    print(f"Konvertierung jeweiliger 4er-Tuple in einem uint32")
    print()
    print("Mit Python built-int Left-Shift-Operator")
    result = quaternary_8bit_to_unary_32bit(raw_data, to32_np_fn)
    for r in result:
        print_binary_pattern_32(r)
    print()
    print("Mit numpy left_shift Funktion")
    result = quaternary_8bit_to_unary_32bit(raw_data, to32_bit_op)
    for r in result:
        print_binary_pattern_32(r)
image-demo/README.md
New file
@@ -0,0 +1,20 @@
# Demonstration von Zusammenspiel numpy/PIL und PySide6
## Build python file from ui
```shell
pyside6-project build imgdemo.json
```
## Install as development mode (editable)
```
pip install -e .
```
## Run the application after install
```
imgdemo
```
image-demo/pyproject.toml
New file
@@ -0,0 +1,19 @@
[build-system]
requires = ["setuptools"]
build-backend = "setuptools.build_meta"
[project]
name = "image-demo"
version = "0.0.1"
dependencies = [
    "numpy >= 2.0.0",
    "matplotlib >= 3.9",
    "PySide6 >= 6.7"
]
[tool.setuptools.packages.find]
# All the following settings are optional:
where = ["src"]
[project.gui-scripts]
imgdemo = "imgdemo.guimain:main"
image-demo/src/imgdemo/__init__.py
image-demo/src/imgdemo/guimain.py
New file
@@ -0,0 +1,74 @@
import sys
from PySide6.QtGui import QPixmap, QImage
#from PIL.ImageQt import QPixmap, QImage
from PySide6.QtWidgets import QApplication, QMainWindow, QFileDialog
import numpy as np
from PIL import Image
from imgdemo.ui_mainwindow import Ui_MainWindow
class MainWindow(QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.saved_file = ('', '')
        self.chosen_file = ('', '')
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        self.ui.actionChoose_Image.triggered.connect(self.choose_image)
        self.ui.actionSave_Image.triggered.connect(self.save_image)
    def choose_image(self):
        self.chosen_file = ('', '') # reset (for safe)
        self.chosen_file = QFileDialog.getOpenFileName(None, "Choose Image", "",
                                                       "Images (*.png *.xpm *.jpg *.tiff) ;; All Filetypes (*.*)")
        print(self.chosen_file)
        if self.chosen_file[0] != '':  # user has chosen a file
            self.display_image()
    def save_image(self):
        self.saved_file = ('', '') # reset for safe
        self.saved_file = QFileDialog.getSaveFileName(None, "Choose Image", "",
                                                       "All (*.*)")
        print(self.saved_file)
    def display_image(self):
        pixmap = QPixmap(self.chosen_file[0])
        self.ui.origin_img.setPixmap(pixmap)
        # now read the image and show it via Image in other container
        with Image.open(self.chosen_file[0]) as img:
            image = np.asarray(img, dtype=np.uint8)
            self.display_numpy_image(image)
    def display_numpy_image(self, image):
        height, width, channel = image.shape
        print(height, width, channel)
        bytes_per_line = channel * width  # color
        img_format = QImage.Format.Format_RGBX8888
        if channel == 4:
            img_format =  QImage.Format.Format_ARGB32
        elif channel == 3:
            img_format = QImage.Format.Format_RGB888
        qImg = QImage(image.data, width, height, bytes_per_line, img_format).rgbSwapped()
        pixmap = QPixmap(qImg)
        self.ui.result_img.setPixmap(pixmap)
def main():
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec())
    pass
if __name__ == "__main__":
    main()
image-demo/src/imgdemo/mainwindow.ui
New file
@@ -0,0 +1,107 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>800</width>
    <height>600</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>Image Demo</string>
  </property>
  <widget class="QWidget" name="centralwidget">
   <layout class="QVBoxLayout" name="verticalLayout_3">
    <item>
     <layout class="QHBoxLayout" name="horizontalLayout">
      <item>
       <widget class="QGroupBox" name="origin_container">
        <property name="title">
         <string>Origin Image</string>
        </property>
        <layout class="QVBoxLayout" name="verticalLayout_2">
         <item>
          <widget class="QLabel" name="origin_img">
           <property name="text">
            <string>Source</string>
           </property>
          </widget>
         </item>
        </layout>
       </widget>
      </item>
      <item>
       <widget class="QGroupBox" name="result_container">
        <property name="title">
         <string>Filtered Image</string>
        </property>
        <layout class="QVBoxLayout" name="verticalLayout">
         <item>
          <widget class="QLabel" name="result_img">
           <property name="text">
            <string>Result</string>
           </property>
          </widget>
         </item>
        </layout>
       </widget>
      </item>
     </layout>
    </item>
    <item>
     <widget class="QPushButton" name="pushButton">
      <property name="text">
       <string>Dummy Widget</string>
      </property>
     </widget>
    </item>
   </layout>
  </widget>
  <widget class="QMenuBar" name="menubar">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
     <width>800</width>
     <height>22</height>
    </rect>
   </property>
   <widget class="QMenu" name="menuFile">
    <property name="title">
     <string>&amp;File</string>
    </property>
    <addaction name="actionChoose_Image"/>
    <addaction name="actionSave_Image"/>
   </widget>
   <addaction name="menuFile"/>
  </widget>
  <widget class="QStatusBar" name="statusbar"/>
  <action name="actionChoose_Image">
   <property name="icon">
    <iconset theme="QIcon::ThemeIcon::FolderOpen"/>
   </property>
   <property name="text">
    <string>Choose Image</string>
   </property>
   <property name="shortcut">
    <string>Ctrl+O</string>
   </property>
  </action>
  <action name="actionSave_Image">
   <property name="icon">
    <iconset theme="QIcon::ThemeIcon::DocumentSave"/>
   </property>
   <property name="text">
    <string>Save Image</string>
   </property>
   <property name="shortcut">
    <string>Ctrl+S</string>
   </property>
  </action>
 </widget>
 <resources/>
 <connections/>
</ui>
image-demo/src/imgdemo/ui_mainwindow.py
New file
@@ -0,0 +1,111 @@
# -*- coding: utf-8 -*-
################################################################################
## Form generated from reading UI file 'mainwindow.ui'
##
## Created by: Qt User Interface Compiler version 6.7.2
##
## WARNING! All changes made in this file will be lost when recompiling UI file!
################################################################################
from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale,
    QMetaObject, QObject, QPoint, QRect,
    QSize, QTime, QUrl, Qt)
from PySide6.QtGui import (QAction, QBrush, QColor, QConicalGradient,
    QCursor, QFont, QFontDatabase, QGradient,
    QIcon, QImage, QKeySequence, QLinearGradient,
    QPainter, QPalette, QPixmap, QRadialGradient,
    QTransform)
from PySide6.QtWidgets import (QApplication, QGroupBox, QHBoxLayout, QLabel,
    QMainWindow, QMenu, QMenuBar, QPushButton,
    QSizePolicy, QStatusBar, QVBoxLayout, QWidget)
class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        if not MainWindow.objectName():
            MainWindow.setObjectName(u"MainWindow")
        MainWindow.resize(800, 600)
        self.actionChoose_Image = QAction(MainWindow)
        self.actionChoose_Image.setObjectName(u"actionChoose_Image")
        icon = QIcon(QIcon.fromTheme(QIcon.ThemeIcon.FolderOpen))
        self.actionChoose_Image.setIcon(icon)
        self.actionSave_Image = QAction(MainWindow)
        self.actionSave_Image.setObjectName(u"actionSave_Image")
        icon1 = QIcon(QIcon.fromTheme(QIcon.ThemeIcon.DocumentSave))
        self.actionSave_Image.setIcon(icon1)
        self.centralwidget = QWidget(MainWindow)
        self.centralwidget.setObjectName(u"centralwidget")
        self.verticalLayout_3 = QVBoxLayout(self.centralwidget)
        self.verticalLayout_3.setObjectName(u"verticalLayout_3")
        self.horizontalLayout = QHBoxLayout()
        self.horizontalLayout.setObjectName(u"horizontalLayout")
        self.origin_container = QGroupBox(self.centralwidget)
        self.origin_container.setObjectName(u"origin_container")
        self.verticalLayout_2 = QVBoxLayout(self.origin_container)
        self.verticalLayout_2.setObjectName(u"verticalLayout_2")
        self.origin_img = QLabel(self.origin_container)
        self.origin_img.setObjectName(u"origin_img")
        self.verticalLayout_2.addWidget(self.origin_img)
        self.horizontalLayout.addWidget(self.origin_container)
        self.result_container = QGroupBox(self.centralwidget)
        self.result_container.setObjectName(u"result_container")
        self.verticalLayout = QVBoxLayout(self.result_container)
        self.verticalLayout.setObjectName(u"verticalLayout")
        self.result_img = QLabel(self.result_container)
        self.result_img.setObjectName(u"result_img")
        self.verticalLayout.addWidget(self.result_img)
        self.horizontalLayout.addWidget(self.result_container)
        self.verticalLayout_3.addLayout(self.horizontalLayout)
        self.pushButton = QPushButton(self.centralwidget)
        self.pushButton.setObjectName(u"pushButton")
        self.verticalLayout_3.addWidget(self.pushButton)
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QMenuBar(MainWindow)
        self.menubar.setObjectName(u"menubar")
        self.menubar.setGeometry(QRect(0, 0, 800, 22))
        self.menuFile = QMenu(self.menubar)
        self.menuFile.setObjectName(u"menuFile")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QStatusBar(MainWindow)
        self.statusbar.setObjectName(u"statusbar")
        MainWindow.setStatusBar(self.statusbar)
        self.menubar.addAction(self.menuFile.menuAction())
        self.menuFile.addAction(self.actionChoose_Image)
        self.menuFile.addAction(self.actionSave_Image)
        self.retranslateUi(MainWindow)
        QMetaObject.connectSlotsByName(MainWindow)
    # setupUi
    def retranslateUi(self, MainWindow):
        MainWindow.setWindowTitle(QCoreApplication.translate("MainWindow", u"Image Demo", None))
        self.actionChoose_Image.setText(QCoreApplication.translate("MainWindow", u"Choose Image", None))
#if QT_CONFIG(shortcut)
        self.actionChoose_Image.setShortcut(QCoreApplication.translate("MainWindow", u"Ctrl+O", None))
#endif // QT_CONFIG(shortcut)
        self.actionSave_Image.setText(QCoreApplication.translate("MainWindow", u"Save Image", None))
#if QT_CONFIG(shortcut)
        self.actionSave_Image.setShortcut(QCoreApplication.translate("MainWindow", u"Ctrl+S", None))
#endif // QT_CONFIG(shortcut)
        self.origin_container.setTitle(QCoreApplication.translate("MainWindow", u"Origin Image", None))
        self.origin_img.setText(QCoreApplication.translate("MainWindow", u"Source", None))
        self.result_container.setTitle(QCoreApplication.translate("MainWindow", u"Filtered Image", None))
        self.result_img.setText(QCoreApplication.translate("MainWindow", u"Result", None))
        self.pushButton.setText(QCoreApplication.translate("MainWindow", u"Dummy Widget", None))
        self.menuFile.setTitle(QCoreApplication.translate("MainWindow", u"&File", None))
    # retranslateUi
num-int/src/numint/ui_mainwindow.py
File was deleted
stundenplan/src/pygraph/graphdemo.py
@@ -2,6 +2,9 @@
class Graph:
    """
    represents an undirected and unweighted Graph
    """
    def __init__(self):
        self._adjacent: dict[int, set] = {}
        self._vertex_attribute: dict[int, dict] = {}
@@ -25,7 +28,7 @@
            u_neighbor.add(v)
        pass
    def add_edges(self, u: int, adjacent:[int]):
    def add_edges(self, u: int, adjacent: list[int]):
        for v in adjacent:
            self.add_edge(u, v)
        pass
@@ -44,7 +47,7 @@
        """
        if vertex not in self._adjacent:
            raise ValueError(f"Graph does not include vertex {vertex}")
        old_attributes = self._vertex_attribute.get(vertex)
        old_attributes = self._vertex_attribute[vertex]
        self._vertex_attribute[vertex] = old_attributes | properties
        return self
        pass
@@ -75,7 +78,7 @@
    def adjacent_of(self, vertex: int):
        if vertex not in self._adjacent:
            raise ValueError(f"Graph does not include vertex {vertex}")
        return sorted( self._adjacent.get(vertex) )
        return sorted( self._adjacent[vertex] )
    def for_each_edges(self, action: Callable[[int, int], Any]):
        """
@@ -87,21 +90,18 @@
            for end in self.adjacent_of(start):
                (first, second) = (start, end) if (start >= end) else (end, start)
            if first in visited_edges:
                visited_adjacent = visited_edges.get(first)
                #visited_adjacent = visited_edges.get(first)
                visited_adjacent = visited_edges[first]
                if second not in visited_adjacent:
                    visited_adjacent.add(second)
                    action(start, end)
            else:
                adjacent = set()
                adjacent: set[int] = set()
                visited_edges[first] = adjacent
                adjacent.add(second)
                action(start, end)
    def get_lecture_name(self, vertex: int):
        pass
    def set_lecture_name(self, vertex: int, name: str):
        pass
    def __repr__(self):
        text = ""
stundenplan/src/pygraph/shortestpath.py
@@ -1,9 +1,10 @@
import collections
from typing import Mapping
from pygraph.graphdemo import Graph
def bfs(g: Graph, start: int) -> {int:int|None}:
def bfs(g: Graph, start: int) -> Graph:
    """
    :param g:
@@ -26,3 +27,53 @@
                g.merge_attribute(v, visited)
                queue.append(v)
    return tree
def bfs_dict(g: Graph, start: int) -> Mapping[int, int|None]:
    tree = {start:None}
    queue = collections.deque()
    VISITED = "visited"
    not_visited = {VISITED: False}
    visited = {VISITED: True}
    g.for_each_vertices(lambda v : g.merge_attribute(v, not_visited))
    queue.append(start)  # append() is the enqueue() operation of a Queue
    g.merge_attribute(start, visited)
    while queue:
        u = queue.popleft()  # popleft() is the dequeue() operation of a Queue
        for v in g.adjacent_of(u):
            if not g.get_attribute(v)[VISITED]:
                tree[v] = u
                g.merge_attribute(v, visited)
                queue.append(v)
    return tree
    pass
def find_path(g: Graph, u: int, v: int) -> list[int]:
    tree = bfs_dict(g, v)
    path = [u]
    while (current := path[-1]) != v:
        precedent = tree[current]
        path.append(precedent)
    return path
def find_path_gpt(g: Graph, u: int, v: int) -> list[int]:
    # Erstelle einen BFS-Baum, beginnend bei Knoten v
    bfs_tree = bfs_dict(g, v)
    # Wenn u nicht in bfs_tree ist, gibt es keinen Pfad von u nach v
    if u not in bfs_tree:
        return []  # Kein Pfad gefunden
    # Den Pfad von u nach v rekonstruieren
    path = []
    current = u
    while current is not None:
        path.append(current)
        current = bfs_tree[current]
    # Den Pfad umkehren, da wir rückwärts von u nach v gehen
    path.reverse()
    return path
stundenplan/tests/pygraph/shortestpath_tests.py
@@ -1,26 +1,57 @@
import unittest
from pygraph.graphdemo import Graph
from pygraph.shortestpath import bfs
from pygraph.shortestpath import bfs, bfs_dict, find_path, find_path_gpt
class ShortestPathTestCase(unittest.TestCase):
    def test_bfs(self):
        g = Graph()
        g.add_edges(0, [1, 2])
        g.add_edges(1, [0, 3, 4])
        g.add_edges(2, [0, 4, 6, 7])
        g.add_edges(3, [1])
        g.add_edges(4, [1, 2, 5])
        g.add_edges(5, [4])
        g.add_edges(6, [2])
        g.add_edges(7, [2])
        #print(g)
        # self.assertEqual(True, False)  # add assertion here
        g.add_edges(1, [3, 4])
        g.add_edges(2, [4, 6, 7])
        g.add_edges(4, [5])
        print(g)
        print("#")
        tree = bfs(g, 0)
        print(tree)
    def test_bfs_dict(self):
        g = Graph()
        g.add_edges(0, [1, 2])
        g.add_edges(1, [3, 4])
        g.add_edges(2, [4, 6, 7])
        g.add_edges(4, [5])
        print(g)
        tree = bfs_dict(g, 6)
        print("Tree from Vertex 6")
        print(tree)
    def test_find_path(self):
        g = Graph()
        g.add_edges(0, [1, 2])
        g.add_edges(1, [3, 4])
        g.add_edges(2, [4, 6, 7])
        g.add_edges(4, [5])
        print(g)
        (u, v) = (6, 5)
        path = find_path(g, 6, 5)
        print(f"path from {u} to {v}")
        print(path)
    def test_find_path_gpt(self):
        g = Graph()
        g.add_edges(0, [1, 2])
        g.add_edges(1, [3, 4])
        g.add_edges(2, [4, 6, 7])
        g.add_edges(4, [5])
        print(g)
        (u, v) = (6, 5)
        path = find_path_gpt(g, 6, 5)
        print(f"path from {u} to {v}")
        print(path)
if __name__ == '__main__':
    unittest.main()