I have written a function where I want to detect the edges of an image using the Canny algorithm. I then want to extract the 2d array of this image, and then flatten it into a 1d array.
def canny_detection(image):
# Convert to grayscale and convert the image to float
RGB = img_as_float(color.rgb2gray(image))
# Apply Canny edge detection algorithm
edge_canny = feature.canny(RGB, 3).astype(int)
#Get output array
canny_arr = np.array(edge_canny)
# Flatten output array
canny_flat = canny_arr.flatten()
return canny_flat
However, when I call the function with an example image, the output is just a huge array of 0s. I'm sure that's not right. I've tested the canny algorithm on the image, and the resulting image is correct. But the problem is when I want to get the vector of the image.
Can anyone help with this?
I suspect problem might be in that line:
edge_canny = feature.canny(RGB, 3).astype(int)
please replace it with
edge_canny = feature.canny(RGB, 3)
print(edge_canny)
edge_canny = edge_canny.astype(int)
print(edge_canny)
and check what it prints, if first is some nonzero float values <1.0 and second is 0s, that probably means that feature.canny produces values from 0.0 to 1.0 and then you lose it converting to int.
EDIT: Fixed my code.
Related
I have two 128x128 black and white images, black background and white image in centre of image. One is an input into another function and the output is the output of this function. I need to take the bottom right 64x64 pixels of the output image and compare them to the bottom right 64x64 of the input image array. Where a pixel is white in the output I need the corresponding pixel in the input to be made white also.
I have tried just using numpy slicing to cut and paste the 64x64 part of the output over the input but occasionally the input is larger than the output so this is not desirable.
I've tried looping through a single image with the following type of looping code:
for (i,row) in enumerate(image_mesh):
for (j,pixel) in enumerate(row):
print(pixel)
But am stuck on how to loop through two arrays simultaneously and compare individual pixels. Sample images attached.
Assuming your images are RGB and you are trying to compare black (0, 0, 0) against white (1, 1, 1)
You can simply compare them
comparison_ab = np.allclose(img_a[64:, 64:, :], img_b[64:, 64:, :]) # 64x64 bool
and create an RGB image out of it using broadcasting
comparison_ab * np.array([1, 1, 1])[None, None, :] # 64x64x3 float
or take the elementwise minimum
np.minimum(img_a, img_b)
Couldn't get Nil's answer to work but resolved it using:
#convert input files to bool
img_a=input > 200
img_b=output[:,:,0] > 200
comparison = img_b>img_a
#convert from bool to uint8
comparison=comparison.astype('uint8')*255
Converting to a bool array was helpful, a direct greater than operation separated out the differences nicely. I was able to paste this in with a slicing operation easily.
I am writing some codes to cut two seprate ROI regions in an numpy array. The array is a mask array with boolean values and it consists of two major left and right parts.
I need to crops those left and right parts from my original numpy array. My codes are as follow which are a section of function (image and masked are passed to this function)
if mask.shape[-1] > 0:
# We're treating all instances as one, so collapse the mask into one layer
mask = (np.sum(mask, -1, keepdims=True) >= 1)
zeros=np.zeros(image.shape)
#splash = np.where(mask, image, gray).astype(np.uint8)
splash = np.where(mask, image, zeros).astype(np.uint8)
I am not sure how to achieve this as I am really new to bumpy. I can splash the imge but what I need is differt I ned to crop two left and right parts and for this I need to crop or reshape the mask array. I have attached a splashed output sample to this thread
This is a very typical problem in computer vision. One popular solution to this is the Connected Component Labeling (or CCL). OpenCV has already an implementation for this:
https://docs.opencv.org/3.4/d3/dc0/group__imgproc__shape.html#gaedef8c7340499ca391d459122e51bef5
Then you may use blob analysis to crop out the objects:
https://docs.opencv.org/3.4/d0/d7a/classcv_1_1SimpleBlobDetector.html
I need to replace a pixel value in an image as an operation in the graph. Doing this beforehand is unfortunately not an option as it is part of an optimization process.
As a fix until I come up with a solution, I am simply using tf.py_func() but since this operation has to be executed a lot it's very slow and inefficient.
# numpy function to perturb a single pixel in an image
def perturb_image(pixel, img):
# At each pixel's x,y position, assign its rgb value
x_pos, y_pos, r, g, b = pixel
rgb = [r,g,b]
img[x_pos, y_pos] = rgb
return img
# pixel is a 1D tensor like [x-dim,y-dim,R,G,B]
# image is tensor with shape (x-dim,y-dim,3)
img_perturbed = tf.py_func(perturb_image,[pixel, image], tf.uint8)
One way I thought of is using tf.add(perturbation, image) where both have the same dimension and perturbation is all zeros except at the pixel location which needs its RGB-values changed to the same value as defined in pixel from the above code snippet. Unfortunately, I would need to rewrite a lot of code surrounding this operation which I am trying to avoid.
Can you think of a solution to replace py_func with another tensorflow operation using the same inputs?
Any help is much appreciated.
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 a 2D array that I want to create an image from. I want to transform the image array of dimensions 140x120 to an array of 140x120x3 by stacking the same array 3 times (to get a grayscale image to use with skimage).
I tried the following:
image = np.uint8([image, image, image])
which results in a 3x120x140 image. How can I reorder the array to get 120x140x3 instead?
np.dstack([image, image, image]) (docs) will return an array of the desired shape, but whether this has the right semantics for your application depends on your image generation library.