Second ex refactored
parent
37c80f45cf
commit
6ced34f623
|
@ -12,9 +12,9 @@ import UZ_utils as uz
|
||||||
|
|
||||||
def excercise_one() -> None:
|
def excercise_one() -> None:
|
||||||
image = one_a()
|
image = one_a()
|
||||||
#one_b(image)
|
one_b(image)
|
||||||
#one_c(image)
|
one_c(image)
|
||||||
#one_d(100, 200, 200, 400, image)
|
one_d(100, 200, 200, 400, image)
|
||||||
one_e()
|
one_e()
|
||||||
|
|
||||||
def one_a() -> npt.NDArray[np.float64]:
|
def one_a() -> npt.NDArray[np.float64]:
|
||||||
|
@ -143,10 +143,10 @@ def excercise_two() -> None:
|
||||||
pixels in the source image is greater or lower than the given threshold.
|
pixels in the source image is greater or lower than the given threshold.
|
||||||
"""
|
"""
|
||||||
two_a()
|
two_a()
|
||||||
#two_b('./images/bird.jpg', 100, 20)
|
two_b('./images/bird.jpg', 100, 20)
|
||||||
#two_c('./images/bird.jpg', 20, 100)
|
two_c('./images/bird.jpg', 20, 100)
|
||||||
#two_d()
|
two_d()
|
||||||
#two_e(uz.imread_gray('./images/bird.jpg', uz.ImageType.uint8).astype(np.uint8))
|
two_e(uz.imread_gray('./images/bird.jpg', uz.ImageType.uint8).astype(np.uint8))
|
||||||
|
|
||||||
|
|
||||||
def two_a() -> tuple[npt.NDArray[np.float64], npt.NDArray[np.uint8]]:
|
def two_a() -> tuple[npt.NDArray[np.float64], npt.NDArray[np.uint8]]:
|
||||||
|
@ -180,48 +180,6 @@ def two_a() -> tuple[npt.NDArray[np.float64], npt.NDArray[np.uint8]]:
|
||||||
plt.show()
|
plt.show()
|
||||||
return (image, binary_mask)
|
return (image, binary_mask)
|
||||||
|
|
||||||
|
|
||||||
def my_hist_for_loop(image: npt.NDArray[np.float64], number_of_bins: int) -> npt.NDArray[np.float64]:
|
|
||||||
bin_restrictions = np.arange(0, 1, 1 / number_of_bins)
|
|
||||||
bins = np.zeros(number_of_bins).astype(np.float64)
|
|
||||||
|
|
||||||
for pixel in image.reshape(-1):
|
|
||||||
# https://stackoverflow.com/a/16244044
|
|
||||||
bins[np.argmax(bin_restrictions > pixel)] += 1
|
|
||||||
|
|
||||||
return bins / np.sum(bins)
|
|
||||||
|
|
||||||
# Much faster implementation than for loop
|
|
||||||
def my_hist(image: npt.NDArray[np.float64], number_of_bins: int, img_typ: uz.ImageType) -> npt.NDArray[np.float64]:
|
|
||||||
if img_typ == uz.ImageType.float64:
|
|
||||||
bins = np.arange(0, 1, 1 / number_of_bins)
|
|
||||||
elif img_typ == uz.ImageType.uint8:
|
|
||||||
bins = np.arange(0, 255, 255/number_of_bins)
|
|
||||||
|
|
||||||
# Put pixels into classes
|
|
||||||
# ex. binsize = 10 then 0.4 would map into 4
|
|
||||||
binarray = np.digitize(image.reshape(-1), bins).astype(np.uint8)
|
|
||||||
|
|
||||||
# Now count those values
|
|
||||||
binarray = np.unique(binarray, return_counts=True)
|
|
||||||
|
|
||||||
counts = binarray[1].astype(np.float64) # Get the counts out of tuple
|
|
||||||
|
|
||||||
# Check if there is any empty bin
|
|
||||||
empty_bins = []
|
|
||||||
bins = binarray[0]
|
|
||||||
for i in range(1, number_of_bins + 1):
|
|
||||||
if i not in bins:
|
|
||||||
empty_bins.append(i)
|
|
||||||
|
|
||||||
# Add empty bins with zeros
|
|
||||||
if empty_bins != []:
|
|
||||||
for i in empty_bins:
|
|
||||||
counts = np.insert(counts, i - 1, 0)
|
|
||||||
|
|
||||||
return counts / np.sum(counts)
|
|
||||||
|
|
||||||
|
|
||||||
def two_b(image_path: str, number_of_bins_first: int, number_of_bins_second: int) -> None:
|
def two_b(image_path: str, number_of_bins_first: int, number_of_bins_second: int) -> None:
|
||||||
"""
|
"""
|
||||||
Write a function myhist that accepts a grayscale image and the number of bins that
|
Write a function myhist that accepts a grayscale image and the number of bins that
|
||||||
|
@ -239,20 +197,20 @@ def two_b(image_path: str, number_of_bins_first: int, number_of_bins_second: int
|
||||||
sum of all cells. Why is that?
|
sum of all cells. Why is that?
|
||||||
Answer:
|
Answer:
|
||||||
"""
|
"""
|
||||||
image = uz.imread_gray(image_path, uz.ImageType.uint8)
|
image = uz_image.imread_gray(image_path, uz_image.ImageType.uint8)
|
||||||
|
|
||||||
H1 = my_hist(image, number_of_bins_first, uz.ImageType.uint8)
|
H1 = uz_image.get_image_bins(image, number_of_bins_first)
|
||||||
H2 = my_hist(image, number_of_bins_second, uz.ImageType.uint8)
|
H2 = uz_image.get_image_bins(image, number_of_bins_second)
|
||||||
|
|
||||||
fig, (ax0, ax1, ax2) = plt.subplots(1, 3)
|
fig, axs = plt.subplots(1, 3)
|
||||||
fig.suptitle("Birdie and histgrams")
|
fig.suptitle("Birdie and histograms")
|
||||||
|
|
||||||
ax0.imshow(image, cmap="gray")
|
axs[0].imshow(image, cmap="gray")
|
||||||
ax0.set(title="Birdie image")
|
axs[0].set(title="Birdie image")
|
||||||
ax1.bar(np.arange(number_of_bins_first), H1)
|
axs[1].bar(np.arange(number_of_bins_first), H1)
|
||||||
ax1.set(title="100 bins")
|
axs[1].set(title="100 bins")
|
||||||
ax2.bar(np.arange(number_of_bins_second), H2)
|
axs[2].bar(np.arange(number_of_bins_second), H2)
|
||||||
ax2.set(title="20 bins")
|
axs[2].set(title="20 bins")
|
||||||
|
|
||||||
plt.show()
|
plt.show()
|
||||||
|
|
||||||
|
@ -264,14 +222,14 @@ def two_c(image_path: str, number_of_bins_first: int, number_of_bins_second: int
|
||||||
difference between both versions of the function.
|
difference between both versions of the function.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
image_uint8 = uz.imread_gray(image_path, uz.ImageType.uint8)
|
image_uint8 = uz_image.imread_gray(image_path, uz_image.ImageType.uint8)
|
||||||
image_float64 = uz.imread_gray(image_path, uz.ImageType.float64)
|
image_float64 = uz_image.imread_gray(image_path, uz_image.ImageType.float64)
|
||||||
|
|
||||||
H01 = my_hist(image_uint8, number_of_bins_first, uz.ImageType.uint8)
|
H01 = uz_image.get_image_bins(image_uint8, number_of_bins_first)
|
||||||
H02 = my_hist(image_uint8, number_of_bins_second, uz.ImageType.uint8)
|
H02 = uz_image.get_image_bins(image_uint8, number_of_bins_second)
|
||||||
|
|
||||||
H11 = my_hist(image_float64, number_of_bins_first, uz.ImageType.float64)
|
H11 = uz_image.get_image_bins(image_float64, number_of_bins_first)
|
||||||
H12 = my_hist(image_float64, number_of_bins_second, uz.ImageType.float64)
|
H12 = uz_image.get_image_bins(image_float64, number_of_bins_second)
|
||||||
|
|
||||||
fig, axs = plt.subplots(2, 3)
|
fig, axs = plt.subplots(2, 3)
|
||||||
fig.suptitle("Comparison between two histograms")
|
fig.suptitle("Comparison between two histograms")
|
||||||
|
@ -283,7 +241,7 @@ def two_c(image_path: str, number_of_bins_first: int, number_of_bins_second: int
|
||||||
axs[0, 2].bar(np.arange(number_of_bins_second), H02)
|
axs[0, 2].bar(np.arange(number_of_bins_second), H02)
|
||||||
axs[0, 2].set(title=f'{number_of_bins_second} bins used')
|
axs[0, 2].set(title=f'{number_of_bins_second} bins used')
|
||||||
|
|
||||||
axs[1, 0].imshow(image_float64, cmap="gray")
|
axs[1, 0].imshow(image_uint8, cmap="gray")
|
||||||
axs[1, 0].set(title="Grayscale image in uint8 representation")
|
axs[1, 0].set(title="Grayscale image in uint8 representation")
|
||||||
axs[1, 1].bar(np.arange(number_of_bins_first), H11)
|
axs[1, 1].bar(np.arange(number_of_bins_first), H11)
|
||||||
axs[1, 1].set(title=f'{number_of_bins_first} bins used')
|
axs[1, 1].set(title=f'{number_of_bins_first} bins used')
|
||||||
|
@ -298,49 +256,26 @@ def two_d() -> None:
|
||||||
your web camera and change the lighting of the room. Visualize the histograms for
|
your web camera and change the lighting of the room. Visualize the histograms for
|
||||||
all images for different number of bins and interpret the results.
|
all images for different number of bins and interpret the results.
|
||||||
"""
|
"""
|
||||||
light = uz.imread_gray("./images/ROOM_LIGHTS_ON.jpg", uz.ImageType.float64)
|
imgs = []
|
||||||
darker = uz.imread_gray("./images/ONE_ROOM_LIGH_ON.jpg", uz.ImageType.float64)
|
bins = [20, 60, 100]
|
||||||
dark = uz.imread_gray("./images/DARK.jpg", uz.ImageType.float64)
|
imgs.append(uz_image.imread_gray("./images/ROOM_LIGHTS_ON.jpg", uz_image.ImageType.float64)) # light
|
||||||
|
imgs.append(uz_image.imread_gray("./images/ONE_ROOM_LIGH_ON.jpg", uz_image.ImageType.float64)) # darker
|
||||||
H10 = my_hist(light, 20, uz.ImageType.float64)
|
imgs.append(uz_image.imread_gray("./images/DARK.jpg", uz_image.ImageType.float64)) # dark
|
||||||
H11 = my_hist(light, 60, uz.ImageType.float64)
|
|
||||||
H12 = my_hist(light, 100, uz.ImageType.float64)
|
|
||||||
H20 = my_hist(darker, 20, uz.ImageType.float64)
|
|
||||||
H21 = my_hist(darker, 60, uz.ImageType.float64)
|
|
||||||
H22 = my_hist(darker, 100, uz.ImageType.float64)
|
|
||||||
H30 = my_hist(dark, 20, uz.ImageType.float64)
|
|
||||||
H31 = my_hist(dark, 60, uz.ImageType.float64)
|
|
||||||
H32 = my_hist(dark, 100, uz.ImageType.float64)
|
|
||||||
|
|
||||||
fig, axs = plt.subplots(3, 4)
|
fig, axs = plt.subplots(3, 4)
|
||||||
fig.suptitle("spanskiduh and histgrams")
|
fig.suptitle("Me and my histograms")
|
||||||
|
|
||||||
axs[0, 0].imshow(light, cmap="gray")
|
for i in range(3):
|
||||||
|
for j in range(3):
|
||||||
|
axs[i, j+1].bar(np.arange(bins[j]), uz_image.get_image_bins(imgs[i], bins[j]))
|
||||||
|
axs[i, j+1].set(title=f"Using {bins[j]} bins")
|
||||||
|
|
||||||
|
axs[0, 0].imshow(imgs[0], cmap="gray")
|
||||||
axs[0, 0].set(title="Image in light conditions")
|
axs[0, 0].set(title="Image in light conditions")
|
||||||
axs[0, 1].bar(np.arange(20), H10)
|
axs[1, 0].imshow(imgs[1], cmap="gray")
|
||||||
axs[0, 1].set(title="Using 20 bins")
|
|
||||||
axs[0, 2].bar(np.arange(60), H11)
|
|
||||||
axs[0, 2].set(title="Using 60 bins")
|
|
||||||
axs[0, 3].bar(np.arange(100), H12)
|
|
||||||
axs[0, 3].set(title="Using 100 bins")
|
|
||||||
|
|
||||||
axs[1, 0].imshow(darker, cmap="gray")
|
|
||||||
axs[1, 0].set(title="Image in darker conditions")
|
axs[1, 0].set(title="Image in darker conditions")
|
||||||
axs[1, 1].bar(np.arange(20), H20)
|
axs[2, 0].imshow(imgs[2], cmap="gray")
|
||||||
axs[1, 1].set(title="Using 20 bins")
|
|
||||||
axs[1, 2].bar(np.arange(60), H21)
|
|
||||||
axs[1, 2].set(title="Using 60 bins")
|
|
||||||
axs[1, 3].bar(np.arange(100), H22)
|
|
||||||
axs[1, 3].set(title="Using 100 bins")
|
|
||||||
|
|
||||||
axs[2, 0].imshow(dark, cmap="gray")
|
|
||||||
axs[2, 0].set(title="Image in dark conditions")
|
axs[2, 0].set(title="Image in dark conditions")
|
||||||
axs[2, 1].bar(np.arange(20), H30)
|
|
||||||
axs[2, 1].set(title="Using 20 bins")
|
|
||||||
axs[2, 2].bar(np.arange(60), H31)
|
|
||||||
axs[2, 2].set(title="Using 60 bins")
|
|
||||||
axs[2, 3].bar(np.arange(100), H32)
|
|
||||||
axs[2, 3].set(title="Using 100 bins")
|
|
||||||
|
|
||||||
plt.show()
|
plt.show()
|
||||||
|
|
||||||
|
@ -352,39 +287,7 @@ def two_e(image: npt.NDArray[np.uint8]):
|
||||||
shows the algorithm’s results on different images.
|
shows the algorithm’s results on different images.
|
||||||
References: https://en.wikipedia.org/wiki/Otsu%27s_method
|
References: https://en.wikipedia.org/wiki/Otsu%27s_method
|
||||||
"""
|
"""
|
||||||
treshold_range = np.arange(np.max(image) + 1)
|
return uz_image.calculate_best_treshold_using_otsu_method(image)
|
||||||
criterias = []
|
|
||||||
|
|
||||||
for treshold in treshold_range:
|
|
||||||
# create the thresholded image
|
|
||||||
thresholded_im = np.zeros(image.shape)
|
|
||||||
|
|
||||||
thresholded_im[image >= treshold] = 1
|
|
||||||
|
|
||||||
# compute weights
|
|
||||||
nb_pixels = image.size
|
|
||||||
nb_pixels1 = np.count_nonzero(thresholded_im)
|
|
||||||
weight1 = nb_pixels1 / nb_pixels
|
|
||||||
weight0 = 1 - weight1
|
|
||||||
|
|
||||||
# if one the classes is empty, eg all pixels are below or above the threshold, that threshold will not be considered
|
|
||||||
# in the search for the best threshold
|
|
||||||
if weight1 == 0 or weight0 == 0:
|
|
||||||
continue
|
|
||||||
|
|
||||||
# find all pixels belonging to each class
|
|
||||||
val_pixels1 = image[thresholded_im == 1]
|
|
||||||
val_pixels0 = image[thresholded_im == 0]
|
|
||||||
|
|
||||||
# compute variance of these classes
|
|
||||||
var0 = np.var(val_pixels0) if len(val_pixels0) > 0 else 0
|
|
||||||
var1 = np.var(val_pixels1) if len(val_pixels1) > 0 else 0
|
|
||||||
|
|
||||||
criterias.append( weight0 * var0 + weight1 * var1)
|
|
||||||
|
|
||||||
best_threshold = treshold_range[np.argmin(criterias)]
|
|
||||||
print(f'best treshold is: {best_threshold}')
|
|
||||||
return best_threshold
|
|
||||||
|
|
||||||
|
|
||||||
######################################################
|
######################################################
|
||||||
|
@ -392,7 +295,7 @@ def two_e(image: npt.NDArray[np.uint8]):
|
||||||
######################################################
|
######################################################
|
||||||
|
|
||||||
def excercise_three() -> None:
|
def excercise_three() -> None:
|
||||||
#three_a()
|
three_a()
|
||||||
#mask1, _ = three_b()
|
#mask1, _ = three_b()
|
||||||
#three_c(uz.imread('./images/bird.jpg', uz.ImageType.float64), mask1)
|
#three_c(uz.imread('./images/bird.jpg', uz.ImageType.float64), mask1)
|
||||||
#three_d()
|
#three_d()
|
||||||
|
@ -527,6 +430,9 @@ def three_d():
|
||||||
binary_mask = np.where(binary_mask < TRESHOLD, 0, 1)
|
binary_mask = np.where(binary_mask < TRESHOLD, 0, 1)
|
||||||
binary_mask = uz.convert_float64_array_to_uint8_array(binary_mask)
|
binary_mask = uz.convert_float64_array_to_uint8_array(binary_mask)
|
||||||
|
|
||||||
|
plt.imshow(binary_mask, cmap='gray')
|
||||||
|
plt.show()
|
||||||
|
|
||||||
# If I would invert image here, then we would get crap
|
# If I would invert image here, then we would get crap
|
||||||
# So workaround:
|
# So workaround:
|
||||||
SE_CROSS = cv2.getStructuringElement(cv2.MORPH_CROSS, (2, 2))
|
SE_CROSS = cv2.getStructuringElement(cv2.MORPH_CROSS, (2, 2))
|
||||||
|
@ -582,7 +488,7 @@ def three_e():
|
||||||
sizes = stats[:, -1]
|
sizes = stats[:, -1]
|
||||||
|
|
||||||
for blob in range(n_blobs):
|
for blob in range(n_blobs):
|
||||||
if sizes[blob] > 700:
|
if sizes[blob] > COIN_SIZE:
|
||||||
binary_mask[im_with_separated_blobs == blob] = 0
|
binary_mask[im_with_separated_blobs == blob] = 0
|
||||||
|
|
||||||
three_c(coin_img_color, binary_mask)
|
three_c(coin_img_color, binary_mask)
|
||||||
|
|
|
@ -11,7 +11,7 @@ class ImageType(enum.Enum):
|
||||||
uint8 = 0
|
uint8 = 0
|
||||||
float64 = 1
|
float64 = 1
|
||||||
|
|
||||||
def imread(path: str, type: ImageType) -> npt.NDArray[np.float64] or npt.NDArray[np.uint8]:
|
def imread(path: str, type: ImageType) -> Union[npt.NDArray[np.float64], npt.NDArray[np.uint8]]:
|
||||||
"""
|
"""
|
||||||
Reads an image in RGB order. Image type is transformed from uint8 to float, and
|
Reads an image in RGB order. Image type is transformed from uint8 to float, and
|
||||||
range of values is reduced from [0, 255] to [0, 1].
|
range of values is reduced from [0, 255] to [0, 1].
|
||||||
|
@ -24,10 +24,10 @@ def imread(path: str, type: ImageType) -> npt.NDArray[np.float64] or npt.NDArray
|
||||||
elif type == ImageType.uint8:
|
elif type == ImageType.uint8:
|
||||||
return I
|
return I
|
||||||
|
|
||||||
raise Exception("Unrecognized image format!")
|
raise Exception(f"Unrecognized image format! {type}")
|
||||||
|
|
||||||
|
|
||||||
def imread_gray(path: str, type: ImageType) -> npt.NDArray[np.float64] or npt.NDArray[np.uint8]:
|
def imread_gray(path: str, type: ImageType) -> Union[npt.NDArray[np.float64], npt.NDArray[np.uint8]]:
|
||||||
"""
|
"""
|
||||||
Reads an image in gray. Image type is transformed from uint8 to float, and
|
Reads an image in gray. Image type is transformed from uint8 to float, and
|
||||||
range of values is reduced from [0, 255] to [0, 1].
|
range of values is reduced from [0, 255] to [0, 1].
|
||||||
|
@ -85,7 +85,7 @@ def transform_coloured_image_to_grayscale(image: npt.NDArray[np.float64]) -> npt
|
||||||
|
|
||||||
return grayscale_image
|
return grayscale_image
|
||||||
|
|
||||||
def invert_coloured_image_part(image: npt.NDArray[np.float64] or npt.NDArray[np.uint8], startx: int, endx: int, starty: int, endy: int) -> npt.NDArray[np.float64] or npt.NDArray[np.uint8]:
|
def invert_coloured_image_part(image: Union[npt.NDArray[np.float64], npt.NDArray[np.uint8]], startx: int, endx: int, starty: int, endy: int) -> Union[npt.NDArray[np.float64], npt.NDArray[np.uint8]]:
|
||||||
"""
|
"""
|
||||||
Accepts image, starting position end end position for axes x & y. Returns whole image with inverted part.
|
Accepts image, starting position end end position for axes x & y. Returns whole image with inverted part.
|
||||||
"""
|
"""
|
||||||
|
@ -108,13 +108,13 @@ def invert_coloured_image_part(image: npt.NDArray[np.float64] or npt.NDArray[np.
|
||||||
|
|
||||||
raise Exception("Unrecognized image format!")
|
raise Exception("Unrecognized image format!")
|
||||||
|
|
||||||
def invert_coloured_image(image: npt.NDArray[np.float64] or npt.NDArray[np.uint8]) -> npt.NDArray[np.float64] or npt.NDArray[np.uint8]:
|
def invert_coloured_image(image: Union[npt.NDArray[np.float64], npt.NDArray[np.uint8]]) -> Union[npt.NDArray[np.float64], npt.NDArray[np.uint8]]:
|
||||||
"""
|
"""
|
||||||
Accepts image and inverts it
|
Accepts image and inverts it
|
||||||
"""
|
"""
|
||||||
return invert_coloured_image_part(image, 0, image.shape[0], 0, image.shape[1])
|
return invert_coloured_image_part(image, 0, image.shape[0], 0, image.shape[1])
|
||||||
|
|
||||||
def calculate_best_treshold_using_otsu_method(image: npt.NDArray[np.float64] or npt.NDArray[np.uint8]) -> int:
|
def calculate_best_treshold_using_otsu_method(image: Union[npt.NDArray[np.float64], npt.NDArray[np.uint8]]) -> int:
|
||||||
"""
|
"""
|
||||||
Accepts image and returns best treshold using otsu method
|
Accepts image and returns best treshold using otsu method
|
||||||
"""
|
"""
|
||||||
|
@ -159,3 +159,57 @@ def calculate_best_treshold_using_otsu_method(image: npt.NDArray[np.float64] or
|
||||||
|
|
||||||
best_threshold = treshold_range[np.argmin(criterias)]
|
best_threshold = treshold_range[np.argmin(criterias)]
|
||||||
return best_threshold
|
return best_threshold
|
||||||
|
|
||||||
|
|
||||||
|
def get_image_bins_for_loop(image: Union[npt.NDArray[np.float64], npt.NDArray[np.uint8]], number_of_bins: int) -> npt.NDArray[np.float64]:
|
||||||
|
"""
|
||||||
|
Accepts image in the float64 format or uint8, returns normailzed
|
||||||
|
image bins, histogram
|
||||||
|
"""
|
||||||
|
if image.dtype.type == np.float64 or image.dtype.type == np.uint8:
|
||||||
|
bin_restrictions = np.linspace(np.min(image), np.max(image), num=number_of_bins)
|
||||||
|
else:
|
||||||
|
raise Exception("Unrecognized image format!")
|
||||||
|
|
||||||
|
bins = np.zeros(number_of_bins).astype(np.float64)
|
||||||
|
|
||||||
|
for pixel in image.reshape(-1):
|
||||||
|
# https://stackoverflow.com/a/16244044
|
||||||
|
bins[np.argmax(bin_restrictions > pixel)] += 1
|
||||||
|
|
||||||
|
return bins / np.sum(bins)
|
||||||
|
|
||||||
|
|
||||||
|
# Much faster implementation than for loop
|
||||||
|
def get_image_bins(image: Union[npt.NDArray[np.float64], npt.NDArray[np.uint8]], number_of_bins: int) -> npt.NDArray[np.float64]:
|
||||||
|
"""
|
||||||
|
Accepts image in the float64 format or uint8, returns normailzed
|
||||||
|
image bins, histogram
|
||||||
|
"""
|
||||||
|
if image.dtype.type == np.float64 or image.dtype.type == np.uint8:
|
||||||
|
bins = np.linspace(np.min(image), np.max(image), num=number_of_bins)
|
||||||
|
else:
|
||||||
|
raise Exception("Unrecognized image format!")
|
||||||
|
|
||||||
|
# Put pixels into classes
|
||||||
|
# ex. binsize = 10 then 0.4 would map into 4
|
||||||
|
binarray = np.digitize(image.reshape(-1), bins).astype(np.uint8)
|
||||||
|
|
||||||
|
# Now count those values
|
||||||
|
binarray = np.unique(binarray, return_counts=True)
|
||||||
|
|
||||||
|
counts = binarray[1].astype(np.float64) # Get the counts out of tuple
|
||||||
|
|
||||||
|
# Check if there is any empty bin
|
||||||
|
empty_bins = []
|
||||||
|
bins = binarray[0]
|
||||||
|
for i in range(1, number_of_bins + 1):
|
||||||
|
if i not in bins:
|
||||||
|
empty_bins.append(i)
|
||||||
|
|
||||||
|
# Add empty bins with zeros
|
||||||
|
if empty_bins != []:
|
||||||
|
for i in empty_bins:
|
||||||
|
counts = np.insert(counts, i - 1, 0)
|
||||||
|
|
||||||
|
return counts / np.sum(counts)
|
||||||
|
|
Loading…
Reference in New Issue