#======================================================================= # Non-convolutional image filtering by bitmasks # # Cesare Brizio, 19 January 2023 # # I did something similar around 15 years ago in Visual Basic, # with the heavy burden of a Visual Studio installation. # Thanks to Python, I can provide a working example with in a # much lighter environment. # # The main purpose here is to illustrate the application of # bitmasks and bitwise operations such as bitwise AND # to RGB 24-bit images. # # "cat image" 1.jpg is available as a part of the # Cats vs. Dogs dataset from Kaggle # (https://www.kaggle.com/datasets/pybear/cats-vs-dogs?select=PetImages) #======================================================================= import numpy as np from PIL import Image, ImageOps from matplotlib import pyplot as plt from matplotlib import image as mpimg from matplotlib import colors as mcolors from numpy import asarray import cv2 def plot_image(img: np.array): plt.figure(figsize=(6, 6), dpi=96) plt.title("Cat Image") plt.xlabel("X pixel scaling") plt.ylabel("Y pixels scaling") #plt.imshow(img, cmap='gray'); plt.imshow(img); plt.show() def plot_two_images(img1: np.array, img2: np.array, imm_name): _, ax = plt.subplots(1, 2, figsize=(12, 6), dpi=96) plt.title(imm_name) plt.xlabel("X pixel scaling") plt.ylabel("Y pixels scaling") #ax[0].imshow(img1, cmap='gray') #ax[1].imshow(img2, cmap='gray'); ax[0].imshow(img1) ax[1].imshow(img2); plt.show() Mask_Top_Pass = 0xC0C0C0 #bitwise AND preserves the two "high" bits Mask_High_Pass = 0xE0E0E0 #bitwise AND preserves the three "high" bits Mask_Mid_Pass = 0X7E7E7E #bitwise AND preserves the six "middle" bits Mask_Core_Pass = 0X3C3C3C #bitwise AND preserves the four "middle" bits Mask_Low_Pass = 0X070707 #bitwise AND preserves the three "low" bits Mask_Bot_Pass = 0X030303 #bitwise AND preserves the two "low" bits def BITMASK_HP(img: np.array, curr_mask:float) -> np.array: # A copy of the image - will be overwritten bitmasked_img = img.copy() h, w, c = img.shape #---------------------------------------------------- # BEGIN nested loops to apply the bit mask #---------------------------------------------------- # Iterate over the rows for i in range(h): # Iterate over the columns for j in range(w): # img[i, j] = individual pixel value # Get the current pixel pix = img[i, j] # Apply the bit mask # Store the result to i-th row and j-th column of our convolved_img array bitmasked_img[i, j] = pix & curr_mask #---------------------------------------------------- # END nested loops to apply the bit mask #---------------------------------------------------- return bitmasked_img #======================================================= # LOAD THE ORIGINAL IMAGE by CV2.IMREAD method #======================================================= img_BGR = cv2.imread('C:/Conv_Python/images/1.jpg') img = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2RGB) plot_image(img=img) image_to_save = Image.fromarray(img,'RGB') image_to_save.save("original_image.jpg") #=================================== # Bitmask Top Pass # 0xC0C0C0 #bitwise AND preserves the two "high" bits #=================================== Curr_Title="Cat Image - BITMASK TOP PASS" img_bmask_tp = BITMASK_HP(img=np.array(img), curr_mask=Mask_Top_Pass) img_bmask_tp plot_two_images( img1=img, img2=img_bmask_tp, imm_name=Curr_Title ) image_to_save = Image.fromarray(img_bmask_tp,'RGB') image_to_save.save("bitmasked_tp_img.jpg") #=================================== # Bitmask High Pass # 0xE0E0E0 #bitwise AND preserves the three "high" bits #=================================== Curr_Title="Cat Image - BITMASK HIGH PASS" img_bmask_hp = BITMASK_HP(img=np.array(img), curr_mask=Mask_High_Pass) img_bmask_hp plot_two_images( img1=img, img2=img_bmask_hp, imm_name=Curr_Title ) image_to_save = Image.fromarray(img_bmask_hp,'RGB') image_to_save.save("bitmasked_hp_img.jpg") #=================================== # Bitmask Mid Pass # 0X7E7E7E #bitwise AND preserves the six "middle" bits #=================================== Curr_Title="Cat Image - BITMASK MID PASS" img_bmask_mp = BITMASK_HP(img=np.array(img), curr_mask=Mask_Mid_Pass) img_bmask_mp plot_two_images( img1=img, img2=img_bmask_mp, imm_name=Curr_Title ) image_to_save = Image.fromarray(img_bmask_mp,'RGB') image_to_save.save("bitmasked_mp_img.jpg") #=================================== # Bitmask Core Pass # 0X3C3C3C #bitwise AND preserves the four "middle" bits #=================================== Curr_Title="Cat Image - BITMASK CORE PASS" img_bmask_cp = BITMASK_HP(img=np.array(img), curr_mask=Mask_Core_Pass) img_bmask_cp plot_two_images( img1=img, img2=img_bmask_cp, imm_name=Curr_Title ) image_to_save = Image.fromarray(img_bmask_cp,'RGB') image_to_save.save("bitmasked_cp_img.jpg") #=================================== # Bitmask Low Pass # 0X070707 #bitwise AND preserves the three "low" bits #=================================== Curr_Title="Cat Image - BITMASK LOW PASS" img_bmask_lp = BITMASK_HP(img=np.array(img), curr_mask=Mask_Low_Pass) img_bmask_lp plot_two_images( img1=img, img2=img_bmask_lp, imm_name=Curr_Title ) image_to_save = Image.fromarray(img_bmask_lp,'RGB') image_to_save.save("bitmasked_lp_img.jpg") #=================================== # Bitmask Bottom Pass # 0X030303 #bitwise AND preserves the two "low" bits #=================================== Curr_Title="Cat Image - BITMASK BOTTOM PASS" img_bmask_bp = BITMASK_HP(img=np.array(img), curr_mask=Mask_Bot_Pass) img_bmask_bp plot_two_images( img1=img, img2=img_bmask_bp, imm_name=Curr_Title ) image_to_save = Image.fromarray(img_bmask_bp,'RGB') image_to_save.save("bitmasked_bp_img.jpg")