Created
February 6, 2025 18:29
-
-
Save SqrtRyan/4f250b4e11f52d9818064942156659d2 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from rp import * | |
import numpy as np | |
import torch | |
import torchvision.transforms as T | |
from PIL import Image | |
import cv2 | |
def approximate_matrix_by_rank(matrix, rank=1): | |
""" | |
Approximates a given matrix by another matrix with a specified rank, | |
minimizing the Frobenius norm of the difference between the two matrices. | |
Uses PyTorch and MPS device for acceleration. | |
Args: | |
matrix: The input matrix (NumPy 2D array). | |
rank: The desired rank of the approximation (positive integer). | |
Returns: | |
The rank-R approximation of the input matrix (NumPy 2D array). | |
Returns the original matrix if the desired rank is greater than the | |
matrix's rank. Raises a ValueError if the rank is not a positive | |
integer. | |
Raises: | |
TypeError: if matrix is not a numpy array | |
ValueError: If rank is not a positive integer. | |
""" | |
if not isinstance(matrix, np.ndarray): | |
raise TypeError("Input matrix must be a NumPy array.") | |
if not isinstance(rank, int) or rank <= 0: | |
raise ValueError("Rank must be a positive integer.") | |
rows, cols = matrix.shape | |
if rank > min(rows, cols): | |
return matrix | |
# Convert to PyTorch tensor and move to MPS device | |
matrix_torch = torch.tensor(matrix, dtype=torch.float32).to('mps') | |
# Perform Singular Value Decomposition (SVD) on MPS | |
U, S, V = torch.linalg.svd(matrix_torch) | |
# Keep only the top 'rank' singular values and corresponding vectors | |
S = torch.diag(S[:rank]) | |
U = U[:, :rank] | |
V = V[:rank, :] | |
# Reconstruct the rank-R approximation on MPS | |
approximated_matrix_torch = U @ S @ V | |
# Move back to CPU and convert to NumPy array | |
approximated_matrix = approximated_matrix_torch.cpu().numpy() | |
return approximated_matrix | |
def approximate_image_by_rank(image,rank): | |
image=as_rgb_image(image) | |
image=as_float_image(image) | |
r,g,b=extract_image_channels(image) | |
r=approximate_matrix_by_rank(r,rank) | |
g=approximate_matrix_by_rank(g,rank) | |
b=approximate_matrix_by_rank(b,rank) | |
return compose_image_from_channels(r,g,b) | |
def get_image(): | |
out=load_image_from_webcam() | |
out=resize_image_to_fit(out,height=512,width=512) | |
out=as_rgb_image(out) | |
out=as_float_image(out) | |
return out | |
image=get_image() | |
image=as_float_image(image) | |
image*=0 | |
while True: | |
cam_image=get_image() | |
cam_image=as_rgb_image(as_float_image(cam_image)) | |
delta=cam_image-image | |
delta*=1.51#Moving average | |
delta=approximate_image_by_rank(delta,1) | |
image+=delta | |
display_image(image) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment