| 1 | #=======================================================================
|
| 2 | # Non-convolutional image filtering by bitmasks
|
| 3 | #
|
| 4 | # Cesare Brizio, 19 January 2023
|
| 5 | #
|
| 6 | # I did something similar around 15 years ago in Visual Basic,
|
| 7 | # with the heavy burden of a Visual Studio installation.
|
| 8 | # Thanks to Python, I can provide a working example with in a
|
| 9 | # much lighter environment.
|
| 10 | #
|
| 11 | # The main purpose here is to illustrate the application of
|
| 12 | # bitmasks and bitwise operations such as bitwise AND
|
| 13 | # to RGB 24-bit images.
|
| 14 | #
|
| 15 | # "cat image" 1.jpg is available as a part of the
|
| 16 | # Cats vs. Dogs dataset from Kaggle
|
| 17 | # (https://www.kaggle.com/datasets/pybear/cats-vs-dogs?select=PetImages)
|
| 18 | #=======================================================================
|
| 19 |
|
| 20 | import numpy as np
|
| 21 | from PIL import Image, ImageOps
|
| 22 | from matplotlib import pyplot as plt
|
| 23 | from matplotlib import image as mpimg
|
| 24 | from matplotlib import colors as mcolors
|
| 25 | from numpy import asarray
|
| 26 | import cv2
|
| 27 |
|
| 28 | def plot_image(img: np.array):
|
| 29 | plt.figure(figsize=(6, 6), dpi=96)
|
| 30 | plt.title("Cat Image")
|
| 31 | plt.xlabel("X pixel scaling")
|
| 32 | plt.ylabel("Y pixels scaling")
|
| 33 | #plt.imshow(img, cmap='gray');
|
| 34 | plt.imshow(img);
|
| 35 | plt.show()
|
| 36 |
|
| 37 | def plot_two_images(img1: np.array, img2: np.array, imm_name):
|
| 38 | _, ax = plt.subplots(1, 2, figsize=(12, 6), dpi=96)
|
| 39 | plt.title(imm_name)
|
| 40 | plt.xlabel("X pixel scaling")
|
| 41 | plt.ylabel("Y pixels scaling")
|
| 42 | #ax[0].imshow(img1, cmap='gray')
|
| 43 | #ax[1].imshow(img2, cmap='gray');
|
| 44 | ax[0].imshow(img1)
|
| 45 | ax[1].imshow(img2);
|
| 46 | plt.show()
|
| 47 |
|
| 48 | Mask_Top_Pass = 0xC0C0C0 #bitwise AND preserves the two "high" bits
|
| 49 | Mask_High_Pass = 0xE0E0E0 #bitwise AND preserves the three "high" bits
|
| 50 | Mask_Mid_Pass = 0X7E7E7E #bitwise AND preserves the six "middle" bits
|
| 51 | Mask_Core_Pass = 0X3C3C3C #bitwise AND preserves the four "middle" bits
|
| 52 | Mask_Low_Pass = 0X070707 #bitwise AND preserves the three "low" bits
|
| 53 | Mask_Bot_Pass = 0X030303 #bitwise AND preserves the two "low" bits
|
| 54 |
|
| 55 | def BITMASK_HP(img: np.array, curr_mask:float) -> np.array:
|
| 56 |
|
| 57 | # A copy of the image - will be overwritten
|
| 58 | bitmasked_img = img.copy()
|
| 59 |
|
| 60 | h, w, c = img.shape
|
| 61 |
|
| 62 | #----------------------------------------------------
|
| 63 | # BEGIN nested loops to apply the bit mask
|
| 64 | #----------------------------------------------------
|
| 65 | # Iterate over the rows
|
| 66 | for i in range(h):
|
| 67 | # Iterate over the columns
|
| 68 | for j in range(w):
|
| 69 | # img[i, j] = individual pixel value
|
| 70 | # Get the current pixel
|
| 71 | pix = img[i, j]
|
| 72 | # Apply the bit mask
|
| 73 | # Store the result to i-th row and j-th column of our convolved_img array
|
| 74 | bitmasked_img[i, j] = pix & curr_mask
|
| 75 | #----------------------------------------------------
|
| 76 | # END nested loops to apply the bit mask
|
| 77 | #----------------------------------------------------
|
| 78 |
|
| 79 | return bitmasked_img
|
| 80 |
|
| 81 |
|
| 82 |
|
| 83 |
|
| 84 | #=======================================================
|
| 85 | # LOAD THE ORIGINAL IMAGE by CV2.IMREAD method
|
| 86 | #=======================================================
|
| 87 | img_BGR = cv2.imread('C:/Conv_Python/images/1.jpg')
|
| 88 |
|
| 89 | img = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2RGB)
|
| 90 |
|
| 91 | plot_image(img=img)
|
| 92 |
|
| 93 | image_to_save = Image.fromarray(img,'RGB')
|
| 94 | image_to_save.save("original_image.jpg")
|
| 95 |
|
| 96 |
|
| 97 | #===================================
|
| 98 | # Bitmask Top Pass
|
| 99 | # 0xC0C0C0 #bitwise AND preserves the two "high" bits
|
| 100 | #===================================
|
| 101 | Curr_Title="Cat Image - BITMASK TOP PASS"
|
| 102 | img_bmask_tp = BITMASK_HP(img=np.array(img), curr_mask=Mask_Top_Pass)
|
| 103 | img_bmask_tp
|
| 104 |
|
| 105 | plot_two_images(
|
| 106 | img1=img,
|
| 107 | img2=img_bmask_tp,
|
| 108 | imm_name=Curr_Title
|
| 109 | )
|
| 110 |
|
| 111 | image_to_save = Image.fromarray(img_bmask_tp,'RGB')
|
| 112 | image_to_save.save("bitmasked_tp_img.jpg")
|
| 113 |
|
| 114 |
|
| 115 | #===================================
|
| 116 | # Bitmask High Pass
|
| 117 | # 0xE0E0E0 #bitwise AND preserves the three "high" bits
|
| 118 | #===================================
|
| 119 | Curr_Title="Cat Image - BITMASK HIGH PASS"
|
| 120 | img_bmask_hp = BITMASK_HP(img=np.array(img), curr_mask=Mask_High_Pass)
|
| 121 | img_bmask_hp
|
| 122 |
|
| 123 | plot_two_images(
|
| 124 | img1=img,
|
| 125 | img2=img_bmask_hp,
|
| 126 | imm_name=Curr_Title
|
| 127 | )
|
| 128 |
|
| 129 | image_to_save = Image.fromarray(img_bmask_hp,'RGB')
|
| 130 | image_to_save.save("bitmasked_hp_img.jpg")
|
| 131 |
|
| 132 |
|
| 133 | #===================================
|
| 134 | # Bitmask Mid Pass
|
| 135 | # 0X7E7E7E #bitwise AND preserves the six "middle" bits
|
| 136 | #===================================
|
| 137 | Curr_Title="Cat Image - BITMASK MID PASS"
|
| 138 | img_bmask_mp = BITMASK_HP(img=np.array(img), curr_mask=Mask_Mid_Pass)
|
| 139 | img_bmask_mp
|
| 140 |
|
| 141 | plot_two_images(
|
| 142 | img1=img,
|
| 143 | img2=img_bmask_mp,
|
| 144 | imm_name=Curr_Title
|
| 145 | )
|
| 146 |
|
| 147 | image_to_save = Image.fromarray(img_bmask_mp,'RGB')
|
| 148 | image_to_save.save("bitmasked_mp_img.jpg")
|
| 149 |
|
| 150 |
|
| 151 | #===================================
|
| 152 | # Bitmask Core Pass
|
| 153 | # 0X3C3C3C #bitwise AND preserves the four "middle" bits
|
| 154 | #===================================
|
| 155 | Curr_Title="Cat Image - BITMASK CORE PASS"
|
| 156 | img_bmask_cp = BITMASK_HP(img=np.array(img), curr_mask=Mask_Core_Pass)
|
| 157 | img_bmask_cp
|
| 158 |
|
| 159 | plot_two_images(
|
| 160 | img1=img,
|
| 161 | img2=img_bmask_cp,
|
| 162 | imm_name=Curr_Title
|
| 163 | )
|
| 164 |
|
| 165 | image_to_save = Image.fromarray(img_bmask_cp,'RGB')
|
| 166 | image_to_save.save("bitmasked_cp_img.jpg")
|
| 167 |
|
| 168 |
|
| 169 | #===================================
|
| 170 | # Bitmask Low Pass
|
| 171 | # 0X070707 #bitwise AND preserves the three "low" bits
|
| 172 | #===================================
|
| 173 | Curr_Title="Cat Image - BITMASK LOW PASS"
|
| 174 | img_bmask_lp = BITMASK_HP(img=np.array(img), curr_mask=Mask_Low_Pass)
|
| 175 | img_bmask_lp
|
| 176 |
|
| 177 | plot_two_images(
|
| 178 | img1=img,
|
| 179 | img2=img_bmask_lp,
|
| 180 | imm_name=Curr_Title
|
| 181 | )
|
| 182 |
|
| 183 | image_to_save = Image.fromarray(img_bmask_lp,'RGB')
|
| 184 | image_to_save.save("bitmasked_lp_img.jpg")
|
| 185 |
|
| 186 |
|
| 187 | #===================================
|
| 188 | # Bitmask Bottom Pass
|
| 189 | # 0X030303 #bitwise AND preserves the two "low" bits
|
| 190 | #===================================
|
| 191 | Curr_Title="Cat Image - BITMASK BOTTOM PASS"
|
| 192 | img_bmask_bp = BITMASK_HP(img=np.array(img), curr_mask=Mask_Bot_Pass)
|
| 193 | img_bmask_bp
|
| 194 |
|
| 195 | plot_two_images(
|
| 196 | img1=img,
|
| 197 | img2=img_bmask_bp,
|
| 198 | imm_name=Curr_Title
|
| 199 | )
|
| 200 |
|
| 201 | image_to_save = Image.fromarray(img_bmask_bp,'RGB')
|
| 202 | image_to_save.save("bitmasked_bp_img.jpg")
|