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")
|