The experiment, using IBM's 127-qubit quantum computer Osaka and Qiskit, mixes quantum computing with image processing to place a Quantum Cat, in a Quantum Computer, for a brief second. The code encodes the cats color information into Qubits by using a series of quantum gates to represent RGB values, then retrieves the encoded data and recreates the quantum cat. the process showcases how quantum mechanics can potentially enhance or provide alternative methods for visual data encoding and retrieval. The end goal is to reconstruct the cats average colors from the quantum-encoded data, assessing the fidelity, and analyzing the effects of quantum noise and decoherence. Permanently putting this Quantum Cat into a Quantum Computers entropy, forever, for a second.
Code Walkthrough
1. Image Preparation:
A digital image is uploaded. This image is broken up into a matrix I of pixels, where each pixel p_(ij) has RGB components (R_(ij) ,G_(ij), B_(ij)).
2. Color Data Extraction:
The image I is resized for simplicity, maintaining aspect ratio when necessary, to reduce computational requirements and to adhere to our 127-qubit limit.
The image is then divided into ten horizontal segments, and for each segment S_k, the average color C_k = (R_k, G_k, B_k) is calculated by averaging the RGB values of all pixels within that segment.
3. Quantum State Preparation:
The average RGB values are normalized to a [0, 1] range via C_(norm) = Ck/255.
For each color component, a quantum state vector is prepared using rotation gates:
Red intensity is encoded using R_x(θ_r) where θ_r = 2π⋅R_(norm).
Green intensity is encoded using R_y(θ_g) where θ_g = 2π⋅G_(norm).
Blue intensity is encoded using R_z(θ_b) where θ_b = 2π⋅B_(norm).
The quantum state vector ∣ψ⟩ for each segment is the result of these rotations applied to the initial state ∣000⟩.
4. Quantum Circuit Execution:
A dynamical decoupling sequence is introduced to counteract decoherence. This is a series of X gates applied at specific intervals, effectively flipping the qubits and refocusing their phase evolution.
The state ∣ψ⟩ is then measured. If the measurement projective operator is M, the measurement result m_k for segment k is m_k = ⟨ψk∣ M ∣ψk⟩.
5. Measurement and Error Mitigation:
Calibration circuits are used to characterize the quantum computer's error profile. The Complete Measurement Fitter technique is applied to create a filter that mitigates these errors post-measurement.
6. Image Reconstruction:
The reconstructed image I is formed by assigning to each segment S_k a color based on the measurement outcome m_k.
If m_k corresponds to 111, the segment is colored with C_k; otherwise, it is set to black.
7. Result Visualization and Analysis:
The original, average color, and reconstructed images are visualized to assess the quality of reconstruction and the effects of quantum errors.
8. Data:
The averaged color values and the quantum cats measurement results are serialized into a JSON format for documentation and further analysis.
Code:
# Importing necessary libraries
import cv2
import numpy as np
import matplotlib.pyplot as plt
from qiskit import QuantumCircuit, Aer, execute, IBMQ
from qiskit.visualization import plot_histogram
from qiskit.quantum_info import Statevector
from qiskit.providers.ibmq import least_busy
from qiskit. tools.monitor import job_monitor
from qiskit.ignis.mitigation.measurement import (complete_meas_cal, CompleteMeasFitter)
import json
# Function to encode RGB values into quantum statevectors
def encode_rgb_to_statevector(red, green, blue):
normalized_red = red / 255.0
normalized_green = green / 255.0
normalized_blue = blue / 255.0
qc = QuantumCircuit(3)
qc.rx(2 * np.pi * normalized_red, 0) # Encode red intensity
qc.ry(2 * np.pi * normalized_green, 1) # Encode green intensity
qc.rz(2 * np.pi * normalized_blue, 2) # Encode blue intensity
return Statevector.from_instruction(qc)
# Selecting a quantum provider and backend
IBMQ. save_account('Your_API_Key', overwrite=True)
IBMQ.load_account()
provider = IBMQ.get_provider(hub='ibm-q')
backend = provider.get_backend('ibm_osaka')
print("Using backend: ", backend)
# Loading and processing an image
image_path = "/Users/steventippeconnic/Documents/Pictures/cat1083.jpg"
original_image = cv2.imread(image_path)
original_image_rgb = cv2.cvtColor(original_image, cv2.COLOR_BGR2RGB)
# Setting parameters for image processing
grid_size = 10 # Updated grid size
block_size = 1
resized_image = cv2.resize(original_image_rgb, (grid_size, grid_size), interpolation=cv2.INTER_AREA)
# Initializing lists to store average colors and measurement results
avg_colors = []
measurement_results = []
# Setting up calibration circuits for measurement error mitigation
cal_circuits, state_labels = complete_meas_cal(qr=QuantumCircuit(3).qregs[0], circlabel='measerrormitigationcal')
cal_jobs = execute(cal_circuits, backend=backend, shots=5)
job_monitor(cal_jobs)
cal_results = cal_jobs.result()
meas_fitter = CompleteMeasFitter(cal_results, state_labels)
# Processing each pixel of the resized image
for i in range(grid_size):
for j in range(grid_size):
color = resized_image[i, j]
avg_colors.append(color) # Storing the color of each pixel
statevector = encode_rgb_to_statevector(color[0], color[1], color[2])
qc = QuantumCircuit(3)
qc.initialize(statevector. data, [0, 1, 2])
qc.measure_all()
job = execute(qc, backend=backend, shots=5)
job_monitor(job)
result = job.result()
counts = result.get_counts(qc)
measurement_results.append(1 if '1' in max(counts, key=counts.get) else 0)
# Reconstructing the image based on measurement results
reconstructed_image = np.zeros((grid_size * block_size, grid_size * block_size, 3), dtype=np.uint8)
for i in range(grid_size):
for j in range(grid_size):
idx = i * grid_size + j
if measurement_results[idx]:
reconstructed_image[i*block_size:(i+1)*block_size, j*block_size:(j+1)*block_size] = np.array(avg_colors[idx], dtype=np.uint8)
else:
print(f"Grid Cell [{i},{j}] is set to black due to measurement result 0.")
# Function to interpolate black pixels in the image
def interpolate_black_pixels(image):
height, width, _ = image.shape
for i in range(height):
for j in range(width):
if np.all(image[i, j] == 0): # If the pixel is black
neighboring_colors = []
for di in range(-1, 2):
for dj in range(-1, 2):
ni, nj = i + di, j + dj
if 0 <= ni < height and 0 <= nj < width and not (di == 0 and dj == 0):
if not np.all(image[ni, nj] == 0):
neighboring_colors.append(image[ni, nj])
if neighboring_colors:
image[i, j] = np.mean(neighboring_colors, axis=0)
return image
# Applying the interpolation function
interpolated_reconstructed_image = interpolate_black_pixels(reconstructed_image.copy())
# Plotting the original, pixelated, and reconstructed images
fig, axs = plt.subplots(1, 3, figsize=(15, 5))
axs[0].imshow(original_image_rgb)
axs[0].set_title('Original Image')
axs[0].axis('off')
axs[1].imshow(resized_image)
axs[1].set_title('Pixelated Image')
axs[1].axis('off')
axs[2].imshow(interpolated_reconstructed_image)
axs[2].set_title('Reconstructed Image')
axs[2].axis('off')
plt.tight_layout()
plt. show()
# Convert avg_colors to a list of lists (from a list of NumPy arrays)
avg_colors_list = [color.tolist() for color in avg_colors]
# Update the data to save
data_to_save = {
'average_colors': avg_colors_list,
'measurement_results': measurement_results
}
# Save the results to a JSON file
json_path = "/Users/steventippeconnic/Documents/QC/Quantum_cat_results.json"
with open(json_path, 'w') as json_file:
json.dump(data_to_save, json_file, indent=4)
print(f"Results saved to {json_path}")