import numpy as np
import matplotlib.image as img;
C = 1.0-np.mean(img.imread('circle.png'),axis=2);
C /= np.sum(C);
The image has 256 X 256 pixels. The resulting array C appears to be a 256 X 256 array containing probabilities of each pixel (color, depth, I don't know what the probability is of due to my lack of knowledge of what matplotlib.image.imread does.
I understand the 4th line of code to mean probability values (real data normalized by their sum, so that they sum to 1), but what is the meaning of the formula on the 3rd line of the code, in and outside of the image context, i.e. statistical intuition?
Ultimately, I would like to apply the above probability transformation to a single time series of real data, so I'm wondering if the formula 1.0-np.mean() would still apply for my (non-computer vision, but distributional) application
an image contains pixels.
an image can have one color channel (grayscale) or multiple (red-green-blue).
"depth" is a term describing the gradations of the pixel values. 8 bits are common and that means 2^8 = 256 different levels per channel, or 256^3 = 16.7 million different colors. 1 bit would be black and white. advanced cameras and scanners may have 10, 12, or more bits of depth.
I see nothing involving probabilities here.
img.imread('circle.png') read the image. you will get a numpy array of shape (height, width, 3) because the image is likely in color. the third dimension (dimension 2) expresses the channels of color per pixel. I am guessing that this routine loads images as floating point values with a range of 0.0 to 1.0.
np.mean(..., axis=2) takes the average of all color channels for every pixel. it does an average/mean calculation along axis 2 (the third one), which contains the color values of every pixel. the shape of this array will be (height, width) and represents the input image as grayscale. the weighting of colors is a little questionable. usually the green channel gets more weight (brightest) and the blue channel gets less weight (darkest).
C = 1.0- ... inverts the picture.
np.sum(C) simply sums up all the grayscale pixels of C. you will get a measure of the overall brightness of the picture.
C /= np.sum(C) divides by that brightness measure. you will get a picture with normalized brightness. there is a factor for the image's size (width*height) missing so these values will be very small (dim/dark).
Use this instead (mean instead of sum) to adjust the intensity values to be 0.5 (gray) on average.
C /= np.mean(C) # now 1.0 on average
C *= 0.5
# or just C *= 0.5 / np.mean(C)
I have an image, using steganography I want to save the data in border pixels only.
In other words, I want to save data only in the least significant bits(LSB) of border pixels of an image.
Is there any way to get border pixels to store data( max 15 characters text) in the border pixels?
Plz, help me out...
OBTAINING BORDER PIXELS:
Masking operations are one of many ways to obtain the border pixels of an image. The code would be as follows:
a= cv2.imread('cal1.jpg')
bw = 20 //width of border required
mask = np.ones(a.shape[:2], dtype = "uint8")
cv2.rectangle(mask, (bw,bw),(a.shape[1]-bw,a.shape[0]-bw), 0, -1)
output = cv2.bitwise_and(a, a, mask = mask)
cv2.imshow('out', output)
cv2.waitKey(5000)
After I get an array of ones with the same dimension as the input image, I use cv2.rectangle function to draw a rectangle of zeros. The first argument is the image you want to draw on, second argument is start (x,y) point and the third argument is the end (x,y) point. Fourth argument is the color and '-1' represents the thickness of rectangle drawn (-1 fills the rectangle). You can find the documentation for the function here.
Now that we have our mask, you can use 'cv2.bitwise_and' (documentation) function to perform AND operation on the pixels. Basically what happens is, the pixels that are AND with '1' pixels in the mask, retain their pixel values. Pixels that are AND with '0' pixels in the mask are made 0. This way you will have the output as follows:
.
The input image was :
You have the border pixels now!
Using LSB planes to store your info is not a good idea. It makes sense when you think about it. A simple lossy compression would affect most of your hidden data. Saving your image as JPEG would result in loss of info or severe affected info. If you want to still try LSB, look into bit-plane slicing. Through bit-plane slicing, you basically obtain bit planes (from MSB to LSB) of the image. (image from researchgate.net)
I have done it in Matlab and not quite sure about doing it in python. In Matlab,
the function, 'bitget(image, 1)', returns the LSB of the image. I found a question on bit-plane slicing using python here. Though unanswered, you might want to look into the posted code.
To access border pixel and enter data into it.
A shape of an image is accessed by t= img.shape. It returns a tuple of the number of rows, columns, and channels.A component is RGB which 1,2,3 respectively.int(r[0]) is variable in which a value is stored.
import cv2
img = cv2.imread('xyz.png')
t = img.shape
print(t)
component = 2
img.itemset((0,0,component),int(r[0]))
img.itemset((0,t[1]-1,component),int(r[1]))
img.itemset((t[0]-1,0,component),int(r[2]))
img.itemset((t[0]-1,t[1]-1,component),int(r[3]))
print(img.item(0,0,component))
print(img.item(0,t[1]-1,component))
print(img.item(t[0]-1,0,component))
print(img.item(t[0]-1,t[1]-1,component))
cv2.imwrite('output.png',img)
I am doing some image processing, and I need to check if a binary image is identical to another.
Processing speed isn't an issue, and the simple thing I thought to do was count the white pixels remaining after adding the inverse of image A to image B (these images are very nearly identical, but not quite--some sort of distance metric is the goal).
Note: take the logarithm to linearize the distance
However, in order to create the composite image, I need to include a "mask" that is the same size as the two images.
I am having trouble finding an example of creating the mask online and using it for the Image.composite function.
Here is my code:
compA = ImageOps.invert(imgA)
imgAB = Image.composite(compA,imgB,??? mask)
Right now, I have created a mask of all zeros--however, the composite image does not appear correctly (both A and B are exactly the same images; a mask of all zeros--or all ones for that matter--does not work).
mask = Image.fromarray(np.zeros(imgA.size,dtype=int),mode='L')
imgAB = Image.composite(compA,imgB,mask)
How do I just add these two binary images on top of eachother?
Clearly you're using numpy, so why not just work with numpy arrays and explicitly do whatever arithmetic you want to do in that domain—such as subtracting one image from the other:
arrayA = numpy.asarray( imgA, dtype=int )
arrayB = numpy.asarray( imgB, dtype=int )
arrayDelta = arrayA - arrayB
print( (arrayDelta !=0 ).sum() ) # print the number of non-identical pixels (why count them by hand?)
# NB: this number may be inflated by a factor of 3 if there are 3 identical channels R, G, B
imgDelta = Image.fromarray((numpy.sign(arrayDelta)*127+127).astype('uint8')) # display this image if you want to visualize where the differences are
You could do this even more simply, e.g.
print((numpy.asarray(imgA) != numpy.asarray(imgB)).sum())
but I thought casting to a signed integer type first and then subtracting would allow you to visualize more information (A white and B black -> white pixel in delta; A black and B white -> black pixel in delta)
I have a Pygame black display on which I will draw a letter with white color, as shown in the image below. The size of the display can be anything above 100x100 pixels.
I know I can use something like this to get the surface 2d array:
miSuface = pygame.display.get_surface()
miCoso = pygame.surfarray.array2d(miSuface)
However, I would like to somehow translate this array to a 7x5 bit matrix, on which 0 will correspond to a black pixel and 1 to a white pixel. My final intent is to use the matrix to train a neural network and create a simple OCR. Is there any way I can achieve this? Or is there a better approach to get the 7x5 matrix?
I don't know of any way offhand to compress your array2d into either a smaller array or one with 1-bit of color information. But, you can do the following:
Iterate through the array. If the color is less or equal to 888888, change it to 000000. If it's greater, change it to FFFFFF.
Create a new [7][5] array.
Iterate through again. Add the values of each pixel (black = 0, white = 1) in any given 35th of the array. The sample size will depend entirely on the size of your original array2d. If the average for that block is greater than or equal to 17.5, add a white element to your matrix. If it's less than 17.5, add a black element to your matrix.
I'm not explicitly familiar with the call to pygame.surfarray.array2d(). However, since you're going from a binary color layout to a smaller binary color matrix, you can subdivide the original image using your new proportions in order to properly color the resulting square. I'll give an example.
Say your initial image is 14x10 and you wish to have a 7x5 matrix. Your initial image looks like this:
[[0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,1,0,0,0,0,0,0],
[0,0,0,0,0,0,1,1,1,0,0,0,0,0],
[0,0,0,0,0,1,1,0,1,1,0,0,0,0],
[0,0,0,0,1,1,1,1,1,1,1,0,0,0],
[0,0,0,1,1,1,1,1,1,1,1,1,0,0],
[0,0,1,1,0,0,0,0,0,0,0,1,1,0],
[0,1,1,0,0,0,0,0,0,0,0,0,1,1]]
What you need to do is divide x-wise by 7, and y-wise by 5. Since I picked nice numbers, the slices of the large image you'll be looking at will be 2x2. Take the top left 2x2 block, for example:
[[0,0],
[0,0]] -> [0]
This mini-matrix maps to a single pixel of your 7x5 image. Obviously, in this case it will be 0. Let's look at the bottom right:
[[1,0],
[1,1]] -> [1]
This will map to a value of 1 in your 7x5 image. As you can see, the tricky case in this example is when you have equal 1s and 0s. This will not be a huge issue, fortunately, as your initial image is always at least 100x100.
Applying this method to my example, the shrunk 7x5 image looks like this:
[[0,0,0,0,0,0,0],
[0,0,0,0,0,0,0],
[0,0,0,1,1,0,0],
[0,0,1,1,1,1,0],
[0,1,0,0,0,0,1]]
Psuedocode steps:
Find the size of the mini-matrices (divide by 5 and 7). This will work with an image of any size larger than 7x5.
For each mini-matrix, count the black and white spaces (0 and 1).
Decide whether the space in your final 7x5 matrix should be black or white. In my example, I say that the final space should be black if (number of white squares >= number of black squares). I'm worried that using this will cause problems for you because your pen size is relatively thin compared to the size of your 7x5 divisions. If this is a problem, try something like if (number of white squares * 2 >= number of black squares). This effectively weights the white squares more.
I'm happy to elaborate on this psuedocode. Just let me know.
Finally, if you are still having issues, I might try using a size larger than 7x5. It will give you more precision at a cost to your OCR algorithm. Good luck.