Skip to content

Instantly share code, notes, and snippets.

@SqrtRyan
Created February 6, 2025 18:29
Show Gist options
  • Save SqrtRyan/4f250b4e11f52d9818064942156659d2 to your computer and use it in GitHub Desktop.
Save SqrtRyan/4f250b4e11f52d9818064942156659d2 to your computer and use it in GitHub Desktop.
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