Skip to content

Commit

Permalink
FIX: Resolved characteristic wavelength overestimation via re-scaling
Browse files Browse the repository at this point in the history
* Observed that large characteristic wavelengths are computed if image size is small which leads to poor shapelet kernel size and thus poor analysis
* To combat this, enforced minimum (and adjusted maximum) image dimensions after loading image from src to yield proper wavelength values
* Other minor changes include example 1, where ref. region coordinates have changed with new scaling enforcement
  • Loading branch information
mptino committed Sep 4, 2024
1 parent 76019ba commit 39658d3
Show file tree
Hide file tree
Showing 4 changed files with 22 additions and 19 deletions.
4 changes: 2 additions & 2 deletions examples/example_1/config
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@ method = response_distance
[response_distance]
shapelet_order = default
num_clusters = default
ux = [50, 80]
uy = [150, 180]
ux = [109, 158]
uy = [283, 322]
4 changes: 2 additions & 2 deletions examples/example_1/example_1.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@
image_name = "lamSIM1.png"
shapelet_order = 'default' # can also be integer value to set upper bound
num_clusters = 'default' # default is 20, can be any other positive integer
ux = [50, 80]
uy = [150, 180]
ux = [109, 158]
uy = [283, 322]

## Section 3: code

Expand Down
31 changes: 17 additions & 14 deletions shapelets/self_assembly/misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
'trim_image'
]

def read_image(image_name: str, image_path: str, verbose: bool = True) -> np.ndarray:
def read_image(image_name: str, image_path: str, do_rescale: bool = True, verbose: bool = True) -> np.ndarray:
r"""
Read an image using OpenCV, with some extra handling. By default, re-scales images as greyscale on [-1, 1].
Expand All @@ -42,6 +42,8 @@ def read_image(image_name: str, image_path: str, verbose: bool = True) -> np.nda
* The filename of the image (including extension)
* image_path: str
* The path holding the image
* do_rescale : bool, optional
* Automatically re-scale in accordance with requirements for wavelength algorithm. Default is True
* verbose: bool, optional
* True (default) to print image-related information
Expand All @@ -55,33 +57,34 @@ def read_image(image_name: str, image_path: str, verbose: bool = True) -> np.nda
Re-scaling of image to greyscale on [-1, 1] is intentional to align with the minimum and maximum of shapelet function values.
"""
# Ensure image_path provided exists
if not os.path.exists(image_path):
raise RuntimeError(f'Image path: {image_path} does not exist.')

# read image then ensure image does exist (by evaluating result of cv2.imread)
f = cv2.imread(os.path.join(image_path, image_name))
if not isinstance(f, np.ndarray):
raise RuntimeError(f"Could not read image: {image_name}. Ensure it is located in {image_path} and is of image format.")

# convert to grayscale
f = cv2.cvtColor(f, cv2.COLOR_BGR2GRAY)

# check if re-scaling is needed b/c k-means clustering cannot handle very large images
init_shape = f.shape
resized = False
while any(dim >= 1000 for dim in f.shape):
dim0, dim1 = round(f.shape[0]*0.8), round(f.shape[1]*0.8)
f = cv2.resize(f, dsize=(dim0, dim1))
resized = True
# NOTE: image may require rescaling based on two observed issues:
# 1. scipy.cluster.vq.kmeans yields abort: coredump if one dim of image large (~2000 pixels)
# 2. wavelength algorithm fails if image is too small... need to upsample

# rescale to [-1, 1] greyscale
if do_rescale:
while any(dim >= 2000 for dim in f.shape):
height, width = round(f.shape[0]*0.8), round(f.shape[1]*0.8)
f = cv2.resize(f, dsize=(width, height)) # dsize is opposite numpy convention

while any(dim <= 500 for dim in f.shape):
height, width = round(f.shape[0]*1.2), round(f.shape[1]*1.2)
f = cv2.resize(f, dsize=(width, height)) # dsize is opposite numpy convention

# rescale to [-1, 1] greyscale to match shapelet kernel min/max values
f = ( ((f-f.min()) / (f.max()-f.min())) * 2 ) - 1

if verbose:
print(f"Successfully loaded image: {image_name}")
if resized: print(f"New image dimensions are: {f.shape} as initial size {init_shape} too large")
else: print(f"Image dimensions are: {f.shape}")
print(f"Image loaded with dimensions: {f.shape}")
print(f"Image {image_name} normalized to greyscale on [-1, 1] to align with shapelet kernels")

return f
Expand Down
2 changes: 1 addition & 1 deletion shapelets/self_assembly/wavelength.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
]


def get_wavelength(image: np.ndarray, rng: list = [0, 70], verbose: bool = True) -> float:
def get_wavelength(image: np.ndarray, rng: list = [0, 100], verbose: bool = True) -> float:
r"""
Find characteristic wavelength of an image. Computed using method described in ref. [1].
Expand Down

0 comments on commit 39658d3

Please sign in to comment.