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 have an image i.e an array of pixel values, lets say 5000x5000 (this is the typical size). Now I want to expand it by 2 times to 10kx10k. The value of (0,0) pixel value goes to (0,0), (0,1), (1,0), (1,1) in the expanded image.
After that I am rotating the expanded image using scipy.interpolate.rotate (I believe there is no faster way than this given the size of my array)
Next I have to again resize this 10kx10k array to original size i.e. 5kx5k. To do this I have to take the average pixel values of (0,0), (0,1), (1,0), (1,1) in the expanded image and put them in (0,0) of the new image.
However it turns out that this whole thing is an expensive procedure an takes a lot of time given the size of my array. Is there a faster way to do it?
I am using the following code to expand the original image
#Assume the original image is already given
largeImg=np.zeros((10000,10000), dtype=np.float32)
for j in range(5000):
for k in range(5000):
pixel_value=original_img[j][k]
for x in range((2*k), (2*(k+1))):
for y in range((2*j), (2*(j+1))):
largeImg[y][x] = pixel_value
A similar method is used to reduce the image to original size after rotation.
In numpy you can use repeat:
large_img = original_img.repeat(2, axis=1).repeat(2, axis=0)
and
final_img = 0.25 * rotated_img.reshape(5000,2,5000,2).sum(axis=(3,1))
or use scipy.ndimage.zoom. this can give you smoother results than the numpy methods.
there is a nice library that probably has all the functions you need for handling images, including rotate:
http://scikit-image.org/docs/dev/api/skimage.transform.html#skimage.transform.rotate
I have calculated a matrix of RGB triples for an image and I would like to know the most straightforward technique to display them in an interactive window. I suspect that pygame will be involved. Techniques that minimize the use of pip will be given preference.
result = numpy.zeros([height,width, 3], dtype=numpy.uint8)
pyopencl.enqueue_copy(queue, result, result_g).wait()
surface = pygame.display.set_mode((width, height), pygame.DOUBLEBUF)
# now what?
The solution I was able to get working was this:
result = numpy.zeros([height,width, 3], dtype=numpy.uint8)
pyopencl.enqueue_copy(queue, result, result_g).wait()
surface = pygame.display.set_mode((width, height), pygame.DOUBLEBUF)
rgb2 = numpy.transpose(rgb, (1,0,2))
pygame.pixelcopy.array_to_surface(surface, rgb2)
pygame.display.flip()
The transpose is only necessary because my opencl kernel computed an image arranged as result[y,x,:] = (r,g,b) whereas array_to_surface expects result[x,y,:] (which is backwards from how most framebuffers work). I could alter my opencl kernel to store things in column-major order if I wanted to avoid the transpose.
This solution only works because my surface is the exact same dimensions as my image. I will upvote any other good solutions that work when the surface and the pixel matrix are different dimensions (because someone might find this article when searching for that).
It is difficult to answer exactly without knowing what the code you have shown does, but something like this:
for c in range(width):
for d in range(height):
color = result(d,c)
pygame.draw.line(surface, color, (c,d),(c+1,d))
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.