From d3336b67df757fabe9bd029eb697b198e6b98920 Mon Sep 17 00:00:00 2001 From: Dylan Moraes Date: Thu, 10 Oct 2024 15:34:09 +0530 Subject: [PATCH 1/6] added implementation for brqi --- demos/brqi.md | 97 ++++++++++++ demos/brqi_demo.py | 76 +++++++++ .../embeddings/image_embeddings/__init__.py | 2 + piqture/embeddings/image_embeddings/brqi.py | 90 +++++++++++ .../embeddings/image_embeddings/test_brqi.py | 149 ++++++++++++++++++ 5 files changed, 414 insertions(+) create mode 100644 demos/brqi.md create mode 100644 demos/brqi_demo.py create mode 100644 piqture/embeddings/image_embeddings/brqi.py create mode 100644 tests/embeddings/image_embeddings/test_brqi.py diff --git a/demos/brqi.md b/demos/brqi.md new file mode 100644 index 0000000..299cb28 --- /dev/null +++ b/demos/brqi.md @@ -0,0 +1,97 @@ + +# BRQI Demo + +This demo showcases the Bitplane Representation of Quantum Images (BRQI) using the piQture library. It demonstrates how to load an image, convert it to a quantum circuit using BRQI encoding, and visualize the results. + +## Prerequisites + +- Python 3.7+ +- piQture library +- Qiskit +- NumPy +- Pillow (PIL) +- Matplotlib + +## Installation + +1. Install the required libraries: + +``` +pip install piqture qiskit qiskit-aer numpy pillow matplotlib +``` + +2. Clone the piQture repository or ensure you have the BRQI module available. + +## Usage + +1. Place your input image in a known location. + +2. Update the `image_path` variable in the `main()` function: + + +``` +def main(): + # Path to your input image + image_path = '/Users/dylanmoraes/Downloads/image-1.png' +``` + + +3. Run the script: + +``` +python brqi_demo.py +``` + +## How it works + +The demo follows these steps: + +1. **Load and preprocess the image**: + - Opens the image file + - Converts it to grayscale + - Resizes it to a small dimension (default 4x4) + - Normalizes pixel values to the range [0, 255] + +2. **Create BRQI circuit**: + - Initializes a BRQI object with the image dimensions and pixel values + - Generates the quantum circuit representation of the image + +3. **Visualize results**: + - Displays the original image + - Simulates the quantum circuit using Qiskit's QASM simulator + - Plots a histogram of the measurement results + +## Customization + +- To change the target size of the image, modify the `target_size` parameter in the `load_and_preprocess_image()` function call: + + +```67:67:demos/brqi_demo.py + img_array = load_and_preprocess_image(image_path) +``` + + +- To adjust the number of shots in the quantum simulation, change the `shots` parameter in the `backend.run()` function: + + +``` + job = backend.run(transpiled_circuit, shots=1000) +``` + + +## Understanding the Output + +The script will display two plots: +1. The original grayscale image +2. A histogram of the measurement results from the quantum circuit simulation + +The histogram represents the probability distribution of different quantum states, which encodes the information from the original image in the BRQI format. + +## Troubleshooting + +If you encounter any issues: +- Ensure all required libraries are installed correctly +- Check that the image path is correct and the file exists +- Verify that the piQture library and BRQI module are properly imported + +For more information on the BRQI encoding method and the piQture library, refer to the main piQture documentation. \ No newline at end of file diff --git a/demos/brqi_demo.py b/demos/brqi_demo.py new file mode 100644 index 0000000..e63a39d --- /dev/null +++ b/demos/brqi_demo.py @@ -0,0 +1,76 @@ +import numpy as np +from PIL import Image +from qiskit import QuantumCircuit, transpile +from qiskit_aer import Aer +from qiskit.visualization import plot_histogram +import matplotlib.pyplot as plt + +from piqture.embeddings.image_embeddings.brqi import BRQI + +def load_and_preprocess_image(image_path, target_size=(4, 4)): + # Load the image + img = Image.open(image_path) + + # Convert to grayscale + img = img.convert('L') + + # Resize the image + img = img.resize(target_size) + + # Convert to numpy array + img_array = np.array(img) + + # Normalize pixel values to range [0, 255] + img_array = (img_array / img_array.max() * 255).astype(int) + + return img_array + +def create_brqi_circuit(img_array): + img_dims = img_array.shape + pixel_vals = [img_array.flatten().tolist()] + + # Create BRQI object + brqi_object = BRQI(img_dims, pixel_vals) + + # Generate BRQI circuit + brqi_circuit = brqi_object.brqi() + + return brqi_circuit + +def visualize_results(original_image, brqi_circuit): + # Display original image + plt.figure(figsize=(10, 5)) + plt.subplot(1, 2, 1) + plt.imshow(original_image, cmap='gray') + plt.title('Original Image') + + # Simulate the quantum circuit + backend = Aer.get_backend('qasm_simulator') + transpiled_circuit = transpile(brqi_circuit, backend) + job = backend.run(transpiled_circuit, shots=1000) + result = job.result() + counts = result.get_counts() + + # Plot the histogram of measurement results + plt.subplot(1, 2, 2) + plot_histogram(counts) + plt.title('BRQI Measurement Results') + + plt.tight_layout() + plt.show() + +def main(): + # Path to your input image + image_path = '/path/to/image.jpg' + + # Load and preprocess the image + img_array = load_and_preprocess_image(image_path) + + # Create BRQI circuit + brqi_circuit = create_brqi_circuit(img_array) + + # Visualize results + visualize_results(img_array, brqi_circuit) + +if __name__ == "__main__": + main() diff --git a/piqture/embeddings/image_embeddings/__init__.py b/piqture/embeddings/image_embeddings/__init__.py index 8730187..5ccdf80 100644 --- a/piqture/embeddings/image_embeddings/__init__.py +++ b/piqture/embeddings/image_embeddings/__init__.py @@ -16,10 +16,12 @@ from .ineqr import INEQR from .mcrqi import MCRQI from .neqr import NEQR +from .brqi import BRQI __all__ = [ "FRQI", "NEQR", "INEQR", "MCRQI", + "BRQI", ] diff --git a/piqture/embeddings/image_embeddings/brqi.py b/piqture/embeddings/image_embeddings/brqi.py new file mode 100644 index 0000000..a2f0ebc --- /dev/null +++ b/piqture/embeddings/image_embeddings/brqi.py @@ -0,0 +1,90 @@ + +"""Bitplane Representation of Quantum Images (BRQI)""" + +from __future__ import annotations + +import math +from typing import Union +import numpy as np +from qiskit.circuit import QuantumCircuit + +from piqture.embeddings.image_embedding import ImageEmbedding +from piqture.mixin.image_embedding_mixin import ImageMixin + +class BRQI(ImageEmbedding, ImageMixin): + """Represents images in BRQI representation format.""" + + def __init__( + self, + img_dims: tuple[int, int], + pixel_vals: Union[list[list], np.ndarray], + max_color_intensity: int = 255, + ): + self.max_color_intensity = max_color_intensity + self.validate_max_color_intensity() + + # Convert numpy array to list if necessary + if isinstance(pixel_vals, np.ndarray): + pixel_vals = [pixel_vals.flatten().tolist()] + + ImageEmbedding.__init__(self, img_dims, pixel_vals) + self.color_qubits = int(np.ceil(np.log2(self.max_color_intensity + 1))) + self.feature_dim = int(np.ceil(np.log2(math.prod(self.img_dims)))) + + # Initialize the _circuit attribute + self._circuit = QuantumCircuit(self.feature_dim + self.color_qubits) + + def validate_max_color_intensity(self): + if self.max_color_intensity < 0 or self.max_color_intensity > 255: + raise ValueError( + "Maximum color intensity cannot be less than 0 or greater than 255." + ) + + def validate_number_pixel_lists(self, pixel_vals): + if len(pixel_vals) > 1: + raise ValueError( + f"{self.__class__.__name__} supports grayscale images only. " + f"No. of pixel_lists in pixel_vals must be maximum 1." + ) + + @property + def circuit(self): + """Returns BRQI circuit.""" + return self._circuit + + def pixel_position(self, pixel_pos_binary: str): + """Embeds pixel position values in a circuit.""" + ImageMixin.pixel_position(self.circuit, pixel_pos_binary) + + def pixel_value(self, *args, **kwargs): + """Embeds pixel (color) values in a circuit""" + color_byte = kwargs.get("color_byte") + control_qubits = list(range(self.feature_dim)) + for index, color in enumerate(color_byte): + if color == "1": + self.circuit.mcx( + control_qubits=control_qubits, + target_qubit=self.feature_dim + index + ) + + def brqi(self) -> QuantumCircuit: + """ + Builds the BRQI image representation on a circuit. + + Returns: + QuantumCircuit: final circuit with the BRQI image + representation. + """ + self.pixel_vals = np.array(self.pixel_vals).flatten() + for i in range(self.feature_dim): + self.circuit.h(i) + + num_pixels = math.prod(self.img_dims) + for pixel in range(num_pixels): + color_byte = f"{int(self.pixel_vals[pixel]):0>{self.color_qubits}b}" + self.pixel_value(color_byte=color_byte) + + # Add measurement to all qubits + self.circuit.measure_all() + + return self.circuit diff --git a/tests/embeddings/image_embeddings/test_brqi.py b/tests/embeddings/image_embeddings/test_brqi.py new file mode 100644 index 0000000..5a87a3a --- /dev/null +++ b/tests/embeddings/image_embeddings/test_brqi.py @@ -0,0 +1,149 @@ + +"""Unit test for BRQI class""" + +from __future__ import annotations + +import math +from unittest import mock + +import numpy as np +import pytest +from pytest import raises +from qiskit.circuit import QuantumCircuit + +import sys +import os + +# Add the project root to the Python path +project_root = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', '..')) +sys.path.insert(0, project_root) +print(f"Updated Python path: {sys.path}") + +# Now try to import BRQI +try: + from piqture.embeddings.image_embeddings.brqi import BRQI + print("Successfully imported BRQI") +except ImportError as e: + print(f"Error importing BRQI: {e}") +from piqture.embeddings.image_embeddings.brqi import BRQI + + +MAX_COLOR_INTENSITY = 255 + + +@pytest.fixture(name="brqi_pixel_value") +def brqi_pixel_value_fixture(): + """Fixture for embedding pixel values.""" + + def _circuit(img_dims, pixel_val, color_qubits): + feature_dim = int(np.ceil(np.log2(math.prod(img_dims)))) + pixel_val_bin = f"{int(pixel_val):0>{color_qubits}b}" + test_circuit = QuantumCircuit(feature_dim + color_qubits) + + # Add gates to test_circuit + for index, color in enumerate(pixel_val_bin): + if color == "1": + test_circuit.mcx(list(range(feature_dim)), feature_dim + index) + return test_circuit + + return _circuit + + +class TestBRQI: + """Tests for BRQI image representation class""" + + @pytest.mark.parametrize( + "img_dims, pixel_vals, max_color_intensity", + [ + ((2, 2), [list(range(251, 255))], 300), + ((2, 2), [list(range(251, 255))], -20), + ], + ) + def test_max_color_intensity(self, img_dims, pixel_vals, max_color_intensity): + """Tests value of maximum color intensity.""" + with raises( + ValueError, + match=r"Maximum color intensity cannot be less than \d or greater than \d.", + ): + _ = BRQI(img_dims, pixel_vals, max_color_intensity) + + @pytest.mark.parametrize( + "img_dims, pixel_vals, max_color_intensity", + [((2, 2), [list(range(251, 255))], MAX_COLOR_INTENSITY)], + ) + def test_circuit_property(self, img_dims, pixel_vals, max_color_intensity): + """Tests the BRQI circuits initialization.""" + feature_dim = int(np.ceil(np.log2(math.prod(img_dims)))) + color_qubits = int(np.ceil(np.log2(max_color_intensity + 1))) + test_circuit = QuantumCircuit(feature_dim + color_qubits) + assert BRQI(img_dims, pixel_vals).circuit == test_circuit + + @pytest.mark.parametrize( + "img_dims, pixel_vals, max_color_intensity", + [((2, 2), [list(range(235, 239))], MAX_COLOR_INTENSITY)], + ) + def test_pixel_value( + self, img_dims, pixel_vals, max_color_intensity, brqi_pixel_value + ): + """Tests the circuit received after pixel value embedding.""" + brqi_object = BRQI(img_dims, pixel_vals, max_color_intensity) + color_qubits = int(np.ceil(np.log2(max_color_intensity + 1))) + feature_dim = int(np.ceil(np.log2(math.prod(img_dims)))) + mock_circuit = QuantumCircuit(feature_dim + color_qubits) + + for _, pixel_val in enumerate(pixel_vals[0]): + mock_circuit.clear() + test_circuit = brqi_pixel_value(img_dims, pixel_val, color_qubits) + + with mock.patch( + "piqture.embeddings.image_embeddings.brqi.BRQI.circuit", + new_callable=lambda: mock_circuit, + ): + brqi_object.pixel_value(color_byte=f"{pixel_val:0>{color_qubits}b}") + assert mock_circuit == test_circuit + + @pytest.mark.parametrize( + "img_dims, pixel_vals, max_color_intensity", + [((2, 2), [list(range(1, 5))], MAX_COLOR_INTENSITY)], + ) + def test_brqi( + self, + img_dims, + pixel_vals, + max_color_intensity, + brqi_pixel_value, + ): + """Tests the final BRQI circuit.""" + brqi_object = BRQI(img_dims, pixel_vals, max_color_intensity) + color_qubits = int(np.ceil(np.log2(max_color_intensity + 1))) + feature_dim = int(np.ceil(np.log2(math.prod(img_dims)))) + mock_circuit = QuantumCircuit(feature_dim + color_qubits) + + test_circuit = QuantumCircuit(feature_dim + color_qubits) + test_circuit.h(list(range(feature_dim))) + for index, pixel_val in enumerate(pixel_vals[0]): + pixel_pos_binary = f"{index:0>{feature_dim}b}" + mock_circuit.clear() + test_circuit.compose( + brqi_pixel_value(img_dims, pixel_val, color_qubits), inplace=True + ) + + with mock.patch( + "piqture.embeddings.image_embeddings.brqi.BRQI.circuit", + new_callable=lambda: mock_circuit, + ): + brqi_object.brqi() + assert mock_circuit == test_circuit + + @pytest.mark.parametrize( + "img_dims, pixel_vals, max_color_intensity", + [((2, 2), np.array([[1, 2], [3, 4]]), MAX_COLOR_INTENSITY)], + ) + def test_brqi_with_numpy_array(self, img_dims, pixel_vals, max_color_intensity): + """Tests BRQI with NumPy array input.""" + brqi_object = BRQI(img_dims, pixel_vals, max_color_intensity) + circuit = brqi_object.brqi() + + # Check if the circuit is generated correctly + assert isinstance(circuit, QuantumCircuit) + assert circuit.num_qubits == int(np.ceil(np.log2(math.prod(img_dims)))) + int(np.ceil(np.log2(max_color_intensity + 1))) From 99b274a5440971843263d3584eae4700230242ff Mon Sep 17 00:00:00 2001 From: Dylan Moraes Date: Wed, 30 Oct 2024 11:02:50 +0530 Subject: [PATCH 2/6] modified test cases updated the test cases to run smoothly --- demos/brqi_demo.py | 2 +- .../embeddings/image_embeddings/test_brqi.py | 57 ++++++++----------- 2 files changed, 26 insertions(+), 33 deletions(-) diff --git a/demos/brqi_demo.py b/demos/brqi_demo.py index e63a39d..6b4862b 100644 --- a/demos/brqi_demo.py +++ b/demos/brqi_demo.py @@ -1,7 +1,7 @@ import numpy as np from PIL import Image -from qiskit import QuantumCircuit, transpile from qiskit_aer import Aer +from qiskit import transpile from qiskit.visualization import plot_histogram import matplotlib.pyplot as plt diff --git a/tests/embeddings/image_embeddings/test_brqi.py b/tests/embeddings/image_embeddings/test_brqi.py index 5a87a3a..bcf7b79 100644 --- a/tests/embeddings/image_embeddings/test_brqi.py +++ b/tests/embeddings/image_embeddings/test_brqi.py @@ -1,9 +1,10 @@ - """Unit test for BRQI class""" from __future__ import annotations import math +import os +import sys from unittest import mock import numpy as np @@ -11,20 +12,6 @@ from pytest import raises from qiskit.circuit import QuantumCircuit -import sys -import os - -# Add the project root to the Python path -project_root = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', '..')) -sys.path.insert(0, project_root) -print(f"Updated Python path: {sys.path}") - -# Now try to import BRQI -try: - from piqture.embeddings.image_embeddings.brqi import BRQI - print("Successfully imported BRQI") -except ImportError as e: - print(f"Error importing BRQI: {e}") from piqture.embeddings.image_embeddings.brqi import BRQI @@ -40,10 +27,11 @@ def _circuit(img_dims, pixel_val, color_qubits): pixel_val_bin = f"{int(pixel_val):0>{color_qubits}b}" test_circuit = QuantumCircuit(feature_dim + color_qubits) - # Add gates to test_circuit + # Add gates to test_circuit based on binary representation + control_qubits = list(range(feature_dim)) for index, color in enumerate(pixel_val_bin): if color == "1": - test_circuit.mcx(list(range(feature_dim)), feature_dim + index) + test_circuit.mcx(control_qubits, feature_dim + index) return test_circuit return _circuit @@ -114,26 +102,31 @@ def test_brqi( brqi_pixel_value, ): """Tests the final BRQI circuit.""" + # Create BRQI object and get dimensions brqi_object = BRQI(img_dims, pixel_vals, max_color_intensity) color_qubits = int(np.ceil(np.log2(max_color_intensity + 1))) feature_dim = int(np.ceil(np.log2(math.prod(img_dims)))) - mock_circuit = QuantumCircuit(feature_dim + color_qubits) - + + # Create test circuit with same dimensions test_circuit = QuantumCircuit(feature_dim + color_qubits) + + # Add Hadamard gates test_circuit.h(list(range(feature_dim))) - for index, pixel_val in enumerate(pixel_vals[0]): - pixel_pos_binary = f"{index:0>{feature_dim}b}" - mock_circuit.clear() - test_circuit.compose( - brqi_pixel_value(img_dims, pixel_val, color_qubits), inplace=True - ) - - with mock.patch( - "piqture.embeddings.image_embeddings.brqi.BRQI.circuit", - new_callable=lambda: mock_circuit, - ): - brqi_object.brqi() - assert mock_circuit == test_circuit + + # Add pixel value gates in same order as BRQI implementation + pixel_vals_flat = np.array(pixel_vals).flatten() + for pixel_val in pixel_vals_flat: + pixel_circuit = brqi_pixel_value(img_dims, pixel_val, color_qubits) + test_circuit.compose(pixel_circuit, inplace=True) + + # Add measurements to match BRQI implementation + test_circuit.measure_all() + + # Get the actual circuit + actual_circuit = brqi_object.brqi() + + # Compare circuits + assert actual_circuit == test_circuit @pytest.mark.parametrize( "img_dims, pixel_vals, max_color_intensity", From a61012ee2d17b55ae2e9908d4950619f0be5af04 Mon Sep 17 00:00:00 2001 From: Dylan Moraes Date: Wed, 30 Oct 2024 11:23:08 +0530 Subject: [PATCH 3/6] lint checks modified code to pass the lint checks --- .pre-commit-config.yaml | 2 +- .../embeddings/image_embeddings/__init__.py | 2 +- piqture/embeddings/image_embeddings/brqi.py | 17 +++++++++------ .../embeddings/image_embeddings/test_brqi.py | 21 +++++++++---------- 4 files changed, 23 insertions(+), 19 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 31afae5..9eca9c0 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -34,7 +34,7 @@ repos: rev: v2.17.0 hooks: - id: pylint - args: [--disable=import-error] + args: [--disable=import-error, --disable=R0801] exclude: ^(docs|graphics|utils)/ #- repo: https://github.com/pre-commit/mirrors-mypy diff --git a/piqture/embeddings/image_embeddings/__init__.py b/piqture/embeddings/image_embeddings/__init__.py index 5ccdf80..ee9979a 100644 --- a/piqture/embeddings/image_embeddings/__init__.py +++ b/piqture/embeddings/image_embeddings/__init__.py @@ -12,11 +12,11 @@ Quantum Image Representations (module: piqture.embeddings.image_embeddings) """ +from .brqi import BRQI from .frqi import FRQI from .ineqr import INEQR from .mcrqi import MCRQI from .neqr import NEQR -from .brqi import BRQI __all__ = [ "FRQI", diff --git a/piqture/embeddings/image_embeddings/brqi.py b/piqture/embeddings/image_embeddings/brqi.py index a2f0ebc..cbd483e 100644 --- a/piqture/embeddings/image_embeddings/brqi.py +++ b/piqture/embeddings/image_embeddings/brqi.py @@ -1,16 +1,17 @@ - """Bitplane Representation of Quantum Images (BRQI)""" from __future__ import annotations import math from typing import Union + import numpy as np from qiskit.circuit import QuantumCircuit from piqture.embeddings.image_embedding import ImageEmbedding from piqture.mixin.image_embedding_mixin import ImageMixin + class BRQI(ImageEmbedding, ImageMixin): """Represents images in BRQI representation format.""" @@ -22,19 +23,24 @@ def __init__( ): self.max_color_intensity = max_color_intensity self.validate_max_color_intensity() - + # Convert numpy array to list if necessary if isinstance(pixel_vals, np.ndarray): pixel_vals = [pixel_vals.flatten().tolist()] - + ImageEmbedding.__init__(self, img_dims, pixel_vals) self.color_qubits = int(np.ceil(np.log2(self.max_color_intensity + 1))) self.feature_dim = int(np.ceil(np.log2(math.prod(self.img_dims)))) - + # Initialize the _circuit attribute self._circuit = QuantumCircuit(self.feature_dim + self.color_qubits) def validate_max_color_intensity(self): + """Validate the maximum color intensity value. + + Raises: + ValueError: If max_color_intensity is less than 0 or greater than 255 + """ if self.max_color_intensity < 0 or self.max_color_intensity > 255: raise ValueError( "Maximum color intensity cannot be less than 0 or greater than 255." @@ -63,8 +69,7 @@ def pixel_value(self, *args, **kwargs): for index, color in enumerate(color_byte): if color == "1": self.circuit.mcx( - control_qubits=control_qubits, - target_qubit=self.feature_dim + index + control_qubits=control_qubits, target_qubit=self.feature_dim + index ) def brqi(self) -> QuantumCircuit: diff --git a/tests/embeddings/image_embeddings/test_brqi.py b/tests/embeddings/image_embeddings/test_brqi.py index bcf7b79..f6e612f 100644 --- a/tests/embeddings/image_embeddings/test_brqi.py +++ b/tests/embeddings/image_embeddings/test_brqi.py @@ -3,8 +3,6 @@ from __future__ import annotations import math -import os -import sys from unittest import mock import numpy as np @@ -14,7 +12,6 @@ from piqture.embeddings.image_embeddings.brqi import BRQI - MAX_COLOR_INTENSITY = 255 @@ -106,25 +103,25 @@ def test_brqi( brqi_object = BRQI(img_dims, pixel_vals, max_color_intensity) color_qubits = int(np.ceil(np.log2(max_color_intensity + 1))) feature_dim = int(np.ceil(np.log2(math.prod(img_dims)))) - + # Create test circuit with same dimensions test_circuit = QuantumCircuit(feature_dim + color_qubits) - + # Add Hadamard gates test_circuit.h(list(range(feature_dim))) - + # Add pixel value gates in same order as BRQI implementation pixel_vals_flat = np.array(pixel_vals).flatten() for pixel_val in pixel_vals_flat: pixel_circuit = brqi_pixel_value(img_dims, pixel_val, color_qubits) test_circuit.compose(pixel_circuit, inplace=True) - + # Add measurements to match BRQI implementation test_circuit.measure_all() - + # Get the actual circuit actual_circuit = brqi_object.brqi() - + # Compare circuits assert actual_circuit == test_circuit @@ -136,7 +133,9 @@ def test_brqi_with_numpy_array(self, img_dims, pixel_vals, max_color_intensity): """Tests BRQI with NumPy array input.""" brqi_object = BRQI(img_dims, pixel_vals, max_color_intensity) circuit = brqi_object.brqi() - + # Check if the circuit is generated correctly assert isinstance(circuit, QuantumCircuit) - assert circuit.num_qubits == int(np.ceil(np.log2(math.prod(img_dims)))) + int(np.ceil(np.log2(max_color_intensity + 1))) + assert circuit.num_qubits == int(np.ceil(np.log2(math.prod(img_dims)))) + int( + np.ceil(np.log2(max_color_intensity + 1)) + ) From 24e5b752db195cce86bff98bf6dc0db0a845e7f2 Mon Sep 17 00:00:00 2001 From: Dylan Moraes Date: Wed, 30 Oct 2024 19:57:27 +0530 Subject: [PATCH 4/6] removed demos reverted pre-commit-config.yaml to as it was before removed the demos folder --- .pre-commit-config.yaml | 2 +- demos/brqi.md | 97 ----------------------------------------- demos/brqi_demo.py | 76 -------------------------------- 3 files changed, 1 insertion(+), 174 deletions(-) delete mode 100644 demos/brqi.md delete mode 100644 demos/brqi_demo.py diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 9eca9c0..31afae5 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -34,7 +34,7 @@ repos: rev: v2.17.0 hooks: - id: pylint - args: [--disable=import-error, --disable=R0801] + args: [--disable=import-error] exclude: ^(docs|graphics|utils)/ #- repo: https://github.com/pre-commit/mirrors-mypy diff --git a/demos/brqi.md b/demos/brqi.md deleted file mode 100644 index 299cb28..0000000 --- a/demos/brqi.md +++ /dev/null @@ -1,97 +0,0 @@ - -# BRQI Demo - -This demo showcases the Bitplane Representation of Quantum Images (BRQI) using the piQture library. It demonstrates how to load an image, convert it to a quantum circuit using BRQI encoding, and visualize the results. - -## Prerequisites - -- Python 3.7+ -- piQture library -- Qiskit -- NumPy -- Pillow (PIL) -- Matplotlib - -## Installation - -1. Install the required libraries: - -``` -pip install piqture qiskit qiskit-aer numpy pillow matplotlib -``` - -2. Clone the piQture repository or ensure you have the BRQI module available. - -## Usage - -1. Place your input image in a known location. - -2. Update the `image_path` variable in the `main()` function: - - -``` -def main(): - # Path to your input image - image_path = '/Users/dylanmoraes/Downloads/image-1.png' -``` - - -3. Run the script: - -``` -python brqi_demo.py -``` - -## How it works - -The demo follows these steps: - -1. **Load and preprocess the image**: - - Opens the image file - - Converts it to grayscale - - Resizes it to a small dimension (default 4x4) - - Normalizes pixel values to the range [0, 255] - -2. **Create BRQI circuit**: - - Initializes a BRQI object with the image dimensions and pixel values - - Generates the quantum circuit representation of the image - -3. **Visualize results**: - - Displays the original image - - Simulates the quantum circuit using Qiskit's QASM simulator - - Plots a histogram of the measurement results - -## Customization - -- To change the target size of the image, modify the `target_size` parameter in the `load_and_preprocess_image()` function call: - - -```67:67:demos/brqi_demo.py - img_array = load_and_preprocess_image(image_path) -``` - - -- To adjust the number of shots in the quantum simulation, change the `shots` parameter in the `backend.run()` function: - - -``` - job = backend.run(transpiled_circuit, shots=1000) -``` - - -## Understanding the Output - -The script will display two plots: -1. The original grayscale image -2. A histogram of the measurement results from the quantum circuit simulation - -The histogram represents the probability distribution of different quantum states, which encodes the information from the original image in the BRQI format. - -## Troubleshooting - -If you encounter any issues: -- Ensure all required libraries are installed correctly -- Check that the image path is correct and the file exists -- Verify that the piQture library and BRQI module are properly imported - -For more information on the BRQI encoding method and the piQture library, refer to the main piQture documentation. \ No newline at end of file diff --git a/demos/brqi_demo.py b/demos/brqi_demo.py deleted file mode 100644 index 6b4862b..0000000 --- a/demos/brqi_demo.py +++ /dev/null @@ -1,76 +0,0 @@ -import numpy as np -from PIL import Image -from qiskit_aer import Aer -from qiskit import transpile -from qiskit.visualization import plot_histogram -import matplotlib.pyplot as plt - -from piqture.embeddings.image_embeddings.brqi import BRQI - -def load_and_preprocess_image(image_path, target_size=(4, 4)): - # Load the image - img = Image.open(image_path) - - # Convert to grayscale - img = img.convert('L') - - # Resize the image - img = img.resize(target_size) - - # Convert to numpy array - img_array = np.array(img) - - # Normalize pixel values to range [0, 255] - img_array = (img_array / img_array.max() * 255).astype(int) - - return img_array - -def create_brqi_circuit(img_array): - img_dims = img_array.shape - pixel_vals = [img_array.flatten().tolist()] - - # Create BRQI object - brqi_object = BRQI(img_dims, pixel_vals) - - # Generate BRQI circuit - brqi_circuit = brqi_object.brqi() - - return brqi_circuit - -def visualize_results(original_image, brqi_circuit): - # Display original image - plt.figure(figsize=(10, 5)) - plt.subplot(1, 2, 1) - plt.imshow(original_image, cmap='gray') - plt.title('Original Image') - - # Simulate the quantum circuit - backend = Aer.get_backend('qasm_simulator') - transpiled_circuit = transpile(brqi_circuit, backend) - job = backend.run(transpiled_circuit, shots=1000) - result = job.result() - counts = result.get_counts() - - # Plot the histogram of measurement results - plt.subplot(1, 2, 2) - plot_histogram(counts) - plt.title('BRQI Measurement Results') - - plt.tight_layout() - plt.show() - -def main(): - # Path to your input image - image_path = '/path/to/image.jpg' - - # Load and preprocess the image - img_array = load_and_preprocess_image(image_path) - - # Create BRQI circuit - brqi_circuit = create_brqi_circuit(img_array) - - # Visualize results - visualize_results(img_array, brqi_circuit) - -if __name__ == "__main__": - main() From 8134f33ed1e9b0d4927c814f3a3d471d6d2513ae Mon Sep 17 00:00:00 2001 From: Dylan Moraes Date: Thu, 31 Oct 2024 22:52:09 +0530 Subject: [PATCH 5/6] lint check updated the implementation logic to make it more robust and pass lint checks --- piqture/embeddings/image_embeddings/brqi.py | 32 +++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/piqture/embeddings/image_embeddings/brqi.py b/piqture/embeddings/image_embeddings/brqi.py index cbd483e..57a82d6 100644 --- a/piqture/embeddings/image_embeddings/brqi.py +++ b/piqture/embeddings/image_embeddings/brqi.py @@ -63,9 +63,37 @@ def pixel_position(self, pixel_pos_binary: str): ImageMixin.pixel_position(self.circuit, pixel_pos_binary) def pixel_value(self, *args, **kwargs): - """Embeds pixel (color) values in a circuit""" + """ + Embeds pixel (color) values in a circuit. + + Args: + *args: Variable length argument list. + **kwargs: Arbitrary keyword arguments. + color_byte (str): Binary representation of the color value. + """ + # Get the color byte from kwargs color_byte = kwargs.get("color_byte") - control_qubits = list(range(self.feature_dim)) + if not color_byte: + raise ValueError("color_byte must be provided") + + # Create control qubits list + control_qubits = self._get_control_qubits() + + # Apply gates for each '1' in the color byte + self._apply_color_gates(color_byte, control_qubits) + + def _get_control_qubits(self): + """Helper method to get control qubits.""" + return list(range(self.feature_dim)) + + def _apply_color_gates(self, color_byte: str, control_qubits: list): + """ + Apply quantum gates for color encoding. + + Args: + color_byte (str): Binary representation of the color value. + control_qubits (list): List of control qubits. + """ for index, color in enumerate(color_byte): if color == "1": self.circuit.mcx( From f2453911ab54a631f9d5eedcc1992beb6e43fe94 Mon Sep 17 00:00:00 2001 From: Dylan Moraes Date: Wed, 13 Nov 2024 09:35:28 +0530 Subject: [PATCH 6/6] added demos --- demos/brqi.md | 97 ++++++++++++++++++++++++++++++++++++ demos/brqi_demo.py | 119 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 216 insertions(+) create mode 100644 demos/brqi.md create mode 100644 demos/brqi_demo.py diff --git a/demos/brqi.md b/demos/brqi.md new file mode 100644 index 0000000..94aceb4 --- /dev/null +++ b/demos/brqi.md @@ -0,0 +1,97 @@ + +# BRQI Demo + +This demo showcases the Bitplane Representation of Quantum Images (BRQI) using the piQture library. It demonstrates how to load an image, convert it to a quantum circuit using BRQI encoding, and visualize the results. + +## Prerequisites + +- Python 3.7+ +- piQture library +- Qiskit +- NumPy +- Pillow (PIL) +- Matplotlib + +## Installation + +1. Install the required libraries: + +``` +pip install piqture qiskit qiskit-aer numpy pillow matplotlib +``` + +2. Clone the piQture repository or ensure you have the BRQI module available. + +## Usage + +1. Place your input image in a known location. + +2. Update the `image_path` variable in the `main()` function: + + +``` +def main(): + # Path to your input image + image_path = '/Users/dylanmoraes/Downloads/image-1.png' +``` + + +3. Run the script: + +``` +python brqi_demo.py +``` + +## How it works + +The demo follows these steps: + +1. **Load and preprocess the image**: + - Opens the image file + - Converts it to grayscale + - Resizes it to a small dimension (default 4x4) + - Normalizes pixel values to the range [0, 255] + +2. **Create BRQI circuit**: + - Initializes a BRQI object with the image dimensions and pixel values + - Generates the quantum circuit representation of the image + +3. **Visualize results**: + - Displays the original image + - Simulates the quantum circuit using Qiskit's QASM simulator + - Plots a histogram of the measurement results + +## Customization + +- To change the target size of the image, modify the `target_size` parameter in the `load_and_preprocess_image()` function call: + + +```67:67:demos/brqi_demo.py + img_array = load_and_preprocess_image(image_path) +``` + + +- To adjust the number of shots in the quantum simulation, change the `shots` parameter in the `backend.run()` function: + + +``` + job = backend.run(transpiled_circuit, shots=1000) +``` + + +## Understanding the Output + +The script will display two plots: +1. The original grayscale image +2. A histogram of the measurement results from the quantum circuit simulation + +The histogram represents the probability distribution of different quantum states, which encodes the information from the original image in the BRQI format. + +## Troubleshooting + +If you encounter any issues: +- Ensure all required libraries are installed correctly +- Check that the image path is correct and the file exists +- Verify that the piQture library and BRQI module are properly imported + +For more information on the BRQI encoding method and the piQture library, refer to the main piQture documentation. diff --git a/demos/brqi_demo.py b/demos/brqi_demo.py new file mode 100644 index 0000000..fe1298d --- /dev/null +++ b/demos/brqi_demo.py @@ -0,0 +1,119 @@ +# pylint: disable=R0801 +"""Demo script for BRQI (Binary Representation of Quantum Images) encoding. + +This script demonstrates how to load an image, convert it to BRQI representation, +and visualize the results using quantum circuit simulation. +""" + +import matplotlib.pyplot as plt +import numpy as np +from PIL import Image +from qiskit import transpile +from qiskit.visualization import plot_histogram +from qiskit_aer import Aer + +from piqture.embeddings.image_embeddings.brqi import BRQI + + +def load_and_preprocess_image(image_path, target_size=(4, 4)): + """Load and preprocess an image for BRQI encoding. + + Args: + image_path (str): Path to the input image file + target_size (tuple): Desired dimensions for the resized image (default: (4, 4)) + + Returns: + numpy.ndarray: Preprocessed image array with normalized pixel values + """ + # Load the image + img = Image.open(image_path) + + # Convert to grayscale + img = img.convert("L") + + # Resize the image + img = img.resize(target_size) + + # Convert to numpy array + img_array = np.array(img) + + # Normalize pixel values to range [0, 255] + img_array = (img_array / img_array.max() * 255).astype(int) + + return img_array + + +def create_brqi_circuit(img_array): + """Create a quantum circuit using BRQI encoding for the input image. + + Args: + img_array (numpy.ndarray): Input image array with pixel values + + Returns: + QuantumCircuit: BRQI encoded quantum circuit + """ + img_dims = img_array.shape + pixel_vals = [img_array.flatten().tolist()] + + # Create BRQI object + brqi_object = BRQI(img_dims, pixel_vals) + + # Generate BRQI circuit + brqi_circuit = brqi_object.brqi() + + return brqi_circuit + + +def visualize_results(original_image, brqi_circuit): + """Visualize the original image and quantum circuit simulation results. + + Args: + original_image (numpy.ndarray): The original input image array + brqi_circuit (QuantumCircuit): The BRQI encoded quantum circuit + + Returns: + None: Displays plots of the original image and measurement results + """ + # Display original image + plt.figure(figsize=(10, 5)) + plt.subplot(1, 2, 1) + plt.imshow(original_image, cmap="gray") + plt.title("Original Image") + + # Simulate the quantum circuit + backend = Aer.get_backend("qasm_simulator") + transpiled_circuit = transpile(brqi_circuit, backend) + job = backend.run(transpiled_circuit, shots=1000) + result = job.result() + counts = result.get_counts() + + # Plot the histogram of measurement results + plt.subplot(1, 2, 2) + plot_histogram(counts) + plt.title("BRQI Measurement Results") + + plt.tight_layout() + plt.show() + + +def main(): + """Main function to demonstrate BRQI encoding on an image. + + This function serves as the entry point for the demo script. + It loads an image, creates a BRQI circuit, and visualizes the results. + """ + # Path to your input image + image_path = "/path/to/image.jpg" + + # Load and preprocess the image + img_array = load_and_preprocess_image(image_path) + + # Create BRQI circuit + brqi_circuit = create_brqi_circuit(img_array) + + # Visualize results + visualize_results(img_array, brqi_circuit) + + +if __name__ == "__main__": + main()