OpenCV: How does bitwise_not work? I am experimenting with the OpenCV-library in python. Let's say I read in an image such as: 

import cv2
import matplotlib.pyplot as plt
import numpy as np

img = cv2.imread('imgs/watermark_no_copy.jpg')


This watermark_no_copy image should be part of some python-library.
What I want to do now is to extract just the part of the image that is not white. I have come across the following code to do the job:

 img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
 mask_inv = cv2.bitwise_not(img_gray)
 img_extracted = cv2.bitwise_and(img, img, mask=mask_inv)


I don't fully understand what's going on tho. I understand that we convert the image into a Grayscale at first. A grayscale-image consists of just one color channel (only black and white with different intensity). In my case the background of the image is white and should, therefore, be assigned intensity 255. The colored part of the image, however, is red. It will not be assigned intensity 0. 

Now, how does bitwise_not work? I understand that this should flip any bit 1 to 0 and any bit 0 to 1. However, in that grayscale-image, we don't have just 0 and 1. We have different intensity values. How exactly, does this work? Same question can be applied to the bitwise_and in the last line. bitwise_and of an image with itself, should return just that image, shouldn't it?
It works ... bitwise. Assume the value of a pixel is $200_{10} = 11001000_2$; then the bitwise not of that simply is $00110111_b=55$. Do that for all pixels.

It's not a useful transform in the context of intensities, if you ask me.

If the mask was actuall monochromatic (i.e. exactly black or exactly white in each pixel), it would make more sense.

So, don't "come across code" like that :)