156 lines
4.5 KiB
Python
156 lines
4.5 KiB
Python
#!/usr/bin/env python3
|
|
# -*- coding: utf-8 -*-
|
|
"""
|
|
Created on Tue Dec 20 2022
|
|
|
|
@author: Emilio Martínez <emilio.martinez@fing.edu.uy>
|
|
|
|
Script that reads all images in folder and simulates HDMI tempest capture
|
|
|
|
"""
|
|
|
|
#%%
|
|
|
|
# =============================================================================
|
|
# Imports
|
|
# =============================================================================
|
|
import os
|
|
import time as time
|
|
import numpy as np
|
|
from skimage.io import imread
|
|
from scipy import signal
|
|
from PIL import Image
|
|
from utils.DTutils import TMDS_encoding_original, TMDS_serial
|
|
import sys
|
|
|
|
#%%
|
|
|
|
# Currently supporting png, jpg, jpeg, tif and gif extentions only
|
|
def get_images_names_from_folder (folder):
|
|
images_list = [image for image in os.listdir(folder) \
|
|
if image.endswith('.png') or image.endswith('.jpg') or image.endswith('.jpeg') or \
|
|
image.endswith('.tif') or image.endswith('.tiff') or image.endswith('.gif')]
|
|
return images_list
|
|
|
|
def get_subfolders_names_from_folder(folder):
|
|
subfolders_list = [name for name in os.listdir(folder) if os.path.isdir(os.path.join(folder, name))]
|
|
return subfolders_list
|
|
|
|
def image_transmition_simulation(I, blanking=False):
|
|
|
|
# Encode image for TMDS
|
|
I_TMDS = TMDS_encoding_original (I, blanking = blanking)
|
|
|
|
# Serialize pixel bits and sum channel signals
|
|
I_TMDS_Tx = TMDS_serial(I_TMDS)
|
|
|
|
return I_TMDS_Tx, I_TMDS.shape
|
|
|
|
def image_capture_simulation(I_Tx, h_total, v_total, N_harmonic, noise_std=0,
|
|
fps=60):
|
|
|
|
# Compute pixelrate and bitrate
|
|
px_rate = h_total*v_total*fps
|
|
bit_rate = 10*px_rate
|
|
|
|
# Continuous samples (interpolate)
|
|
interpolator = int(np.ceil(N_harmonic/5)) # Condition for sampling rate and
|
|
sample_rate = interpolator*bit_rate
|
|
Nsamples = interpolator*(10*h_total*v_total)
|
|
if interpolator > 1:
|
|
I_Tx_continuous = np.repeat(I_Tx,interpolator)
|
|
else:
|
|
I_Tx_continuous = I_Tx
|
|
|
|
# Add Gaussian noise
|
|
if noise_std > 0:
|
|
noise_sigma = noise_std/15.968719423 # sqrt(255)~15.968719423
|
|
I_Tx_noisy = I_Tx_continuous + np.random.normal(0, noise_sigma, Nsamples) + 1j*np.random.normal(0, noise_sigma,Nsamples)
|
|
else:
|
|
I_Tx_noisy = I_Tx_continuous
|
|
|
|
# Continuous time array
|
|
t_continuous = np.arange(Nsamples)/sample_rate
|
|
|
|
# AM modulation frequency according to pixel harmonic
|
|
harm = N_harmonic*px_rate
|
|
|
|
# Harmonic oscilator
|
|
baseband_exponential = np.exp(2j*np.pi*harm*t_continuous)
|
|
|
|
usrp_rate = 50e6
|
|
|
|
# AM modulation and SDR sampling
|
|
I_Rx = signal.resample_poly(I_Tx_noisy*baseband_exponential,up=int(usrp_rate), down=sample_rate)
|
|
|
|
# Reshape signal to the image size
|
|
I_capture = signal.resample(I_Rx, h_total*v_total).reshape(v_total,h_total)
|
|
|
|
return I_capture
|
|
|
|
def save_simulation_image(I,path_and_name):
|
|
|
|
v_total,h_total = I.shape
|
|
|
|
I_save = np.zeros((v_total,h_total,3))
|
|
|
|
I_real = np.real(I)
|
|
I_imag = np.imag(I)
|
|
|
|
realmax = I_real.max()
|
|
realmin = I_real.min()
|
|
imagmax = I_imag.max()
|
|
imagmin = I_imag.min()
|
|
|
|
# Stretch contrast on every channel
|
|
I_save[:,:,0] = 255*(I_real-realmin)/(realmax-realmin)
|
|
I_save[:,:,1] = 255*(I_imag-imagmin)/(imagmax-imagmin)
|
|
|
|
im = Image.fromarray(I_save.astype('uint8'))
|
|
im.save(path_and_name)
|
|
|
|
def main():
|
|
|
|
# Get foldername argument
|
|
foldername = sys.argv[-1]
|
|
|
|
# Get images and subfolders names
|
|
images = get_images_names_from_folder(foldername)
|
|
|
|
simulations_folder = foldername+'/simulations/'
|
|
|
|
os.mkdir(simulations_folder)
|
|
|
|
# timestamp for simulation starting
|
|
t1_image = time.time()
|
|
|
|
for image in images:
|
|
|
|
# Read image
|
|
image_path = foldername+'/'+image
|
|
I = imread(image_path)
|
|
|
|
# TMDS coding and bit serialization
|
|
I_Tx, resolution = image_transmition_simulation(I)
|
|
v_res, h_res, _ = resolution
|
|
|
|
# Choose random pixelrate harmonic number
|
|
N_harmonic = np.random.randint(1,10)
|
|
|
|
I_capture = image_capture_simulation(I_Tx, h_res, v_res, N_harmonic)
|
|
|
|
path = simulations_folder+image
|
|
|
|
save_simulation_image(I_capture,path)
|
|
|
|
# timestamp for simulation ending
|
|
t2_image = time.time()
|
|
|
|
t_images = t2_images-t1_images
|
|
|
|
print('\nTiempo total de las '+str(len(images))+' simulaciones:','{:.2f}'.format(t_images)+'s\n')
|
|
|
|
if __name__ == "__main__":
|
|
main()
|
|
|
|
|