Intersecting Arrays in python - python

Ok, so here is my code. om is the array I'm comparing im to. I'm hoping the array is in the format [b, g, r]
import cv2
import numpy as np
import time
om=cv2.imread('RGB.png')
om=om.reshape(1,-1,3)
while True:
cam = cv2.VideoCapture(0)
start=time.time()
while(cam.isOpened()):
ret, im = cam.read()
im=cv2.resize(im,(325,240))
im= im.reshape(1,-1,3)
Ok, so I'm hoping the arrays are based off of all the pixel colours in them and that they are 1D (reshape should have done that?). Duplicates aren't necessary but like, if possible I would like to keep them.
I want to intersect om with im and get the value of the number of elements intersecting. I tried the in1d thing, but it would return Trues and Falses. I'm half wondering if it would be easier to count them?/ the trues.
Also, if I do use the in1d function, does that only count corresponding pixels? (like, that the pixel height and row matter) or is it only pixel bgr? because I am only after bgr.
Basically, I wanna see how many pixels have the same colour value as those in the picture I already have saved.
Btw, I tried using sets, but they were fairly slow and difficult to get into the correct order (I seemed to be getting only one element a set).

intersection = [x for x in list_1 if x in list_2]

Related

Replace certain pixels by integers in numpy array

I have made myself a numpy array from a picture using
from PIL import Image
import numpy as np
image = Image.open(file)
np.array(image)
its shape is (6000, 6000, 4) and in that array I would like to replace pixel values by one number lets say this green pixel [99,214,104,255] will be 1.
I have only 4 such pixels I want to replace with a number and all other pixels will be 0. Is there a fast and efficient way to do so and what is the best way to minimize the size of the data. Is it better to save it as dict(), where keys will be x,y and values, will be integers? Or is it better to save the whole array as it is with the shape it has? I only need the color values the rest is not important for me.
I need to process such a picture as fast as possible because there is one picture every 5 minutes and lets say i would like to store 1 year of data. That is why I'd like to make it as efficient as possible time and space-wise.
If I understand the question correctly, you can use np.where for this:
>>> arr = np.array(image)
>>> COLOR = [99,214,104,255]
>>> np.where(np.all(arr == COLOR, axis=-1), 1, 0)
This will produce a 6000*6000 array with 1 if the pixel is the selected colour, or 0 if not.
How about just storing in a database: the position and value of the pixels you want to modify, the shape of the image, the dtype of the array and the extension (jpg, etc...). You can use that information to build a new image from an array filled with 0.

Concatenating Numpy arrays for OpenCV imshow

Using OpenCV and Python, I want to display the left hand half of one image concatenated with the right-hand half of another image, both of the same size - 512x512 pixels. I have identified several ways of doing this, but I am confused about the behaviour of one method. In the following code, assume that only one of the methods is used at any one time and the rest are commented out:
import cv2
import numpy as np
image1 = cv2.imread('img1.png',0)
image2 = cv2.imread('img2.png',0)
#Method 1 - works
image3 = np.concatenate([image1[:,0:256], image2[:,256:512]], axis=1)
#Method 2 - works
image3 = image1[:,:]
image3[:,256:512] = image2[:,256:512]
#Method 3 - works if I don't create image3 with np.zeros first.
#Otherwise displays black image - all zeros - but print displays correct values
image3 = np.zeros(shape=(512,512), dtype=int)
image3[:,0:256] = image1[:,0:256]
image3[:,256:512] = image2[:,256:512]
print(image3)
cv2.imshow("IMAGE", image3)
cv2.waitKey(0)
cv2.destroyAllWindows()
In method 3, I at first mistakenly thought that the new numpy array image 3 would need to be created first and so created an array filled with zeros and then seemingly overwrote that array with the correct values. When I print that array it displays the correct values, but when I show it as an image using cv2.imshow it is all black (i.e. all zeros). Why the difference? I understand that slicing creates a view, not a copy, but can someone please explain what is happening in method 3 and why cv2.imshow displays the underlying array but print doesn't.
Your problem is in:
np.zeros(shape=(512,512), dtype=int)
imshow will show images coded as float(32 bit) with a range of 0.-1. or 8bit(1-4 channels) with a range of 0-255. You are using int, which is 32 bit (in most cases) and it is not a floating point. What you should do to fix it, is to use np.uint8.
np.zeros(shape=(512,512), dtype=np.uint8)
I think also it can be displayed using matplotlib if you want to keep the int, but I am not 100% sure about it.

How to merge different images into one with numpy - Python

I have 4 different objects with a numpy array (image), how could I merge them into another numpy 3d array (2d and 3 elements in every position) so that I have just one image containing those 4 different image.
For example, lets say I have Img1, Img2, Img3 and Img4, which are independent images and are currently stored in a 2D array like this:
Img1, Img2
Img3, Img4
So what I want is to access to the 2D array where these Img are and then create one single image with them in that order. I have this which works for this example so you can figure out what I need, but I need something generic and efficient, for example to have it a while instead of in 2 nested for:
a = np.hstack((images[0][0], images[0][1]))
b = np.hstack((images[1][0], images[1][1]))
c = np.vstack((a,b))
misc.imshow(c)
This code creates one single image from those I mentioned but I need it to be able to handle any subimage to create the main image, plus need it to be efficient (like having just a while instead of 2 for) :/
Can someone give me a hand please?
Thanks and regards.

Python - matplotlib - imshow - How to influence displayed value of unzoomed image

I need to search outliers in more or less homogeneous images representing some physical array. The images have a resolution which is much higher than the screen resolution. Thus every pixel on screen originates from a block of image pixels. Is there the possibility to customize the algorithm which calculates the displayed value for such a block? Especially the possibility to either use the lowest or the highest value would be helpful.
Thanks in advance
Scipy provides several such filters. To get a new image (new) whose pixels are the maximum/minimum over a w*w block of an original image (img), you can use:
new = scipy.ndimage.filters.maximum_filter(img, w)
new = scipy.ndimage.filters.minimum_filter(img, w)
scipy.ndimage.filters has several other filters available.
If the standard filters don't fit your requirements, you can roll your own. To get you started here is an example that shows how to get the minimum in each block in the image. This function reduces the size of the full image (img) by a factor of w in each direction. It returns a smaller image (new) in which each pixel is the minimum pixel in a w*w block of pixels from the original image. The function assumes the image is in a numpy array:
import numpy as np
def condense(img, w):
new = np.zeros((img.shape[0]/w, img.shape[1]/w))
for i in range(0, img.shape[1]//w):
col1 = i * w
new[:, i] = img[:, col1:col1+w].reshape(-1, w*w).min(1)
return new
If you wanted the maximum, replace min with max.
For the condense function to work well, the size of the full image must be a multiple of w in each direction. The handling of non-square blocks or images that don't divide exactly is left as an exercise for the reader.

Finding coordinates of brightest pixel in an image and entering them into an array

I have been asked to write a program to find 'stars' in an image by converting the image file to a numpy array and generating an array of the coordinates of the brightest pixels in the image above a specified threshold (representing background interference).
Once I have located the brightest pixel in the image I must record its x,y coordinates, and set the value of that pixel and surrounding 10X10 pixel area to zero, effectively removing the star from the image.
I already have a helper code which converts the image to an array, and have attempted to tackle the problem as follows;
I have defined a variable
Max = array.max()
and used a while loop;
while Max >= threshold
coordinates = numpy.where(array == Max) # find the maximum value
however I want this to loop over the whole array for all of the coordinates,not just find the first maximum, and also remove each maximum when found and setting the surrounding 10X10 area to zero. I have thought about using a for loop to do this but am unsure how I should use it since I am new to Python.
I would appreciate any suggestions,
Thanks
There are a number of different ways to do it with just numpy, etc.
There's the "brute force" way:
import Image
import numpy as np
im = Image.open('test.bmp')
data = np.array(im)
threshold = 200
window = 5 # This is the "half" window...
ni, nj = data.shape
new_value = 0
for i, j in zip(*np.where(data > threshold)):
istart, istop = max(0, i-window), min(ni, i+window+1)
jstart, jstop = max(0, j-window), min(nj, j+window+1)
data[istart:istop, jstart:jstop] = new_value
Or the faster approach...
import Image
import numpy as np
import scipy.ndimage
im = Image.open('test.bmp')
data = np.array(im)
threshold = 200
window = 10 # This is the "full" window...
new_value = 0
mask = data > threshold
mask = scipy.ndimage.uniform_filter(mask.astype(np.float), size=window)
mask = mask > 0
data[mask] = new_value
Astronomy.net will do this for you:
If you have astronomical imaging of the sky with celestial coordinates
you do not know—or do not trust—then Astrometry.net is for you. Input
an image and we'll give you back astrometric calibration meta-data,
plus lists of known objects falling inside the field of view.
We have built this astrometric calibration service to create correct,
standards-compliant astrometric meta-data for every useful
astronomical image ever taken, past and future, in any state of
archival disarray. We hope this will help organize, annotate and make
searchable all the world's astronomical information.
You don't even have to upload the images to their website. You can download the source. It is licensed under the GPL and uses NumPy, so you can muck around with it if you need to.
Note that you will need to first convert your bitmap to one of the following: JPEG, GIF, PNG, or FITS image.

Categories