I have an image set which needs to be cropped. I tried implementing different methods to achieve this using user input to specify the pixel range but, none of the methods works. I need to use user input or something similar because the crop sizes is different for other image list and it becomes messy to change code every time.
e.g. of required pixel range [524:1024,275:775]
images = np.array([(plt.imread(fname)) for fname in imglist]).astype(np.int32)
#crop the images
images_crp =np.array([i [input()] for i in images]) # I give input as 524:1024,275:775
#method 2
images_crp = np.array([input() for _ in images]) # I give input as i[524:1024,275:775]
#method 3
images_crp = np.array(i [input():input(),input():input()] for i in images]) # I give input as 524 press enter 1024...
Help is appreciated
Thanks
Related
additional question
I'm working on a project for a family member, I have fairly limited experience with Python. I have written my script on Python, and it works exactly how I need. The code takes a photo and adds a red border to either the length or the width to create a square.
My issue is my family member does not use Python, and after some light research I have come across tkinter for a GUI. I would like to have a text box where the image name can be typed, and that runs the code from the input line.
I have it where you type MyImage.PNG into the console and it saves the border version into the same file. Also, I understand how to design with tkinter--just not how to actually execute my script with the textbox/buttons. Any advice on how to achieve this?
I would like to call images from a file, without having to individually type the image name. Is that possible through an open loop possibly? Or even using a Tkinter widget to read the images file, create a list from the file, and then individually be able to select each image and hit enter.
Thank you!
from PIL import Image, ImageOps
import math
original = input("Please enter an input: ")
im = Image.open(original)
print(im.size)
print(type(im.size))
w, h = im.size
print('width: ', w)
print('height:', h)
if w>h:
x = w - h
b = math.floor(x/2)
a = 0
if w<h:
x = h - w
a = math.floor(x/2)
b = 0
def add_border(input_image, output_image, border, color=0):
img = Image.open(input_image)
if isinstance(border, int) or isinstance(border, tuple):
bimg = ImageOps.expand(img, border=border, fill=color)
else:
raise RuntimeError('Border is not an integer or tuple!')
bimg.save(output_image)
if __name__ == '__main__':
add_border(original,
output_image= 'border' + original,
border=(a,b,a,b),
color='indianred')
Tkinter has an input field function so you could do something like:
from tkinter import *
def Get_Name_Of_Picture():
original=str(PicName.get())
PicName=Entry(screen)
PicName.pack()
Button(screen, text='Enter', command=Get_Name_Of_Picture).pack(side=LEFT)
Something like that(you might have to put the rest of the code in the Get_Name_Of_Picture function) but this will allow the user to type an input into an entry field, and once they are done hit the enter button which will get the string of what was typed and so on.
If you need more advice just comment on this answer and I will try to help.
I am trying to adopt mask_rcnn original code to my dataset.The original code takes xml files and I just modified my code to accept json format. Here is the code
def load_mask(self, image_id, xml=False):
# get details of image
info = self.image_info[image_id]
if xml:
# define anntation file location
path = info['annotation']
# load XML
boxes, w, h = self.extract_boxes(path, xml=True)
else:
with open('D:\Mask_RCNN\Mask_RCNN\dataset\\annots\\annotations.json', 'r') as f:
annots = json.load(f)
found = False
for value in annots.values():
if 'image' in value and value['instance_list']:
if value['image']['original_filename'][:-3] == info['id']:
boxes, w, h = self.extract_boxes(value)
found = True
break
if found:
# create one array for all masks, each on a different channel
masks = zeros([h, w, len(boxes)], dtype='uint8')
else:
stop = "here"
if found:
# create one array for all masks, each on a different channel
masks = zeros([h, w, len(boxes)], dtype='uint8')
else:
stop = "here"
# create masks
class_ids = list()
for i in range(len(boxes)):
box = boxes[i]
row_s, row_e = box[1], box[3]
col_s, col_e = box[0], box[2]
masks[row_s:row_e, col_s:col_e, i] = 1
class_ids.append(self.class_names.index('Penquins'))
return masks, asarray(class_ids, dtype='int32')
# load an image reference
#"""Return the path of the image."""
def image_reference(self, image_id):
info = self.image_info[image_id]
print(info)
return info['path']
It gives me the error
File "C:/PycharmProjects/Mask_RCNN/Mask_RCNN/objects.py", line 197, in load_mask
for i in range(len(boxes)):
UnboundLocalError: local variable 'boxes' referenced before assignment
I tried to debug the code,its throwing an error before creating masks but I am not able to figure out whats wrong. Any idea?
Only if xml is true, it is guaranteed, that boxes gets a value. Otherwise additional conditions have to be fulfilled, which does not seem to be the case.
boxes is initialized in some of the scenarios in load_mask's first if else block, which means it might not exists when you reach if found:. Just declare it in the beginning
def load_mask(self, image_id, xml=False):
# get details of image
info = self.image_info[image_id]
boxes = []
It means that you are trying to iterate over the number of boxes, but your if statements above are constructed in such a way that boxes might not exit by the time this statement gets executed.
try this simple example:
user_input = "no"
if user_input =="yes":
boxes = [1,2,3,4]
else:
pass
print(boxes)
This will result in the same error as you are seeing. Your problem is that both of these if statements must pass before boxes is defined:
if 'image' in value and value['instance_list']:
if value['image']['original_filename'][:-3] == info['id']:
Likely you either need additional logic that ensures the iteration only occurs if certain conditions are met. Or, if boxes is a list you could start your code by defining boxes=[]. In that case the iteration will simply pass over without doing anything as the length of boxes is zero in that case
The problem is that boxes isnt getting declared in line of this for loop, so define boxes as an empty list in the first part of the function
def load_mask(self, image_id, xml=False):
boxes = []
#do all the other stuff here
Then when you do the for loop it should now be declared (unless one of the functions don't return the boxes and give you something else)
Quick tip when doing the for loop, you can do
for i, box in enumerate(boxes):
...
which will not make you define box inside the loop (i will be 0 to len(boxes)-1 and box will be the box with that index)
In the code below i am drawing 3 images from a list (targetset) then displaying them to the screen. Next I am displaying another 3 images (pics) to a different part of the screen. For this second part; on 50% of occasions I want the 'pics' images to be the same as those displayed initially (target set). I am ok with this part, I am setting pics = targetset when x == 0 (basically flipping a coin).
My probleme is, on the other 50% of occasions I want one of the 'pics' set to be the same as one of the orignally showed set (targetset), any one of the three. And i want the remaining 2 to be randomly choosen from the pics list. As it stands, according to my logic, I can only get the 'pics' images to be all the same, or all different as the originally shown images from 'targetset'.
Adding to the problem: When x==0 (making pics=targetset) they all display ok, but when x==1 (meaning make no change) i get the following error message:
pics[i].pos = location[i]
UnboundLocalError: local variable 'pics' referenced before assignment
Here is my code:
#create initial target set
imgList1 = glob.glob(os.path.join('stim','*.png'))
random.shuffle(imgList1)
targetset = [visual.ImageStim(window, img) for img in imgList1[:3]]
#initial target set location
setlocation = [(-2,0),(0,0),(2,0)]
random.shuffle(setlocation)
#create target list
imgList = glob.glob(os.path.join('stim', '*.png'))
random.shuffle(imgList)
pics = [visual.ImageStim(window, img) for img in imgList[:3]]
#set target locations
location = [(1,2),(3,3),(5,5)]
random.shuffle(location)
'''define sequential presentation function'''
def seq():
x = random.randint(0,1)
if x == 0:
pics = targetset
print x
#display initial target set
for i in range(3):
targetset[i].pos = setlocation[i]
targetset[i].draw()
window.flip()
core.wait(3)
#display targets
for i in range(3):
pics[i].pos = location[i]
pics[i].draw()
window.flip()
core.wait(1)
seq()
core.wait(3)
window.close()
quit()
I hope someone can help,
Cheers
S
I see a few possible pitfalls with your code. One is that you are creating two separate lists imgList1 and imgList from the same set of images, then you are randomizing each of these lists separately and pulling the first three elements from each list into targetset and pics respectively. It is possible that these sub-sets will have some overlap in images. From the description of your task, I don't think that this is intentional. I might suggest creating only 1 imgList and then using the imgList.pop() function to pull images from the list. Pop returns the last element from the list and then deletes that element from the list. I think of it like drawing a card from a deck, you cannot draw the card again because it is no longer in the deck. What you're currently doing is like drawing cards from two different decks. You might get the same card twice.
The second problem I see here is that you define a condition for what to do when your coin-flip for x is 0, but you do not define one for when your coin-flip is 1. Currently, it will just display the first 3 images from imgList because that's how you've defined pics. I might suggest defining pics within an if/else block for your x coin-flip. If it's 0, then go with targetset, if it's 1, then randomly choose an element from target list, then copy that element to pics and pop two more images from imgList. As with all coding, there is more than one way to solve this problem, but I'll offer a solution here.
#Outside the trial loop
imgList = glob.glob(os.path.join('stim', '*.png'))
random.shuffle(imgList)
#Inside the trial loop
targetset = []
for i in range(0,3):
targetset.append(imgList.pop())
#Do your display stuff with targetset
if random.randint(0,1) == 0:
pics = targetset
else:
pics = []
pics.append(targetset[random.randint(0,2)])
pics.append(imgList.pop())
pics.append(imgList.pop())
random.shuffle(pics)
#Do your display stuff with pics
I am writing an opencv program where I track position of an object by use of a usb camera. To make sure I get as high frame rate as possible with the camera I am using I made a threaded process that read the images from the camera. The image processing is done in another loop which also writes the object position to the file.
Now I want a way to avoid processing the same frame multiple times. So I thought I could compare the image just processed with that available from the the video stream thread.
First I tried to use if frame1 == frame2, but got error message that "the truth value of an array with more than one element is ambiguous. Use a.any() or a.all()."
After some googling I found cv2.compare and the flag CMP_EQ. Made a sample code, and made it work in some way. However, my question is. How could this be done in an easier or better way?
import cv2
cv2.namedWindow('image1', cv2.WINDOW_NORMAL)
cv2.namedWindow('image2', cv2.WINDOW_NORMAL)
frame1 = cv2.imread("sample1.png")
frame2 = frame1
frame3 = cv2.imread("sample2.png")
compare1 = cv2.compare(frame1,frame2,0)
compare2 = cv2.compare(frame1,frame3,0)
cv2.imshow('image1', compare1)
cv2.imshow('image2', compare2)
if compare1.all():
print "equal"
else:
print "not equal"
if compare2.all():
print "equal"
else:
print "not equal"
cv2.waitKey(0)
cv2.destroyAllWindows()
open("image1.jpg","rb").read() == open("image2.jpg","rb").read()
should tell you if they are exactly the same ...
I was doing something close to what you are doing; I was trying to get the difference. I used the subtract function. It may help you.
UPDATE:
import cv2
import numpy as np
a = cv2.imread("sample1.png")
b = cv2.imread("sample2.png")
difference = cv2.subtract(a, b)
result = not np.any(difference)
if result is True:
print "Pictures are the same"
else:
cv2.imwrite("ed.jpg", difference )
print "Pictures are different, the difference is stored as ed.jpg"
How about giving your Images an index?
Pseudocode:
class Frame
{
cvImage img;
uint idx;
}
Than simply check if the current index is greater than the last one you processed.
It is simple and definitely faster than any image processing based approach.
You can compare the size of two image files as the first level of check for reduced computational complexity. With compression, it is highly unlikely for two different image files to have the same size to the accuracy of the number of bytes. With equal file size, you can then compare the image contents.
You should try something like this.
import cv2
import numpy as np
original = cv2.imread("rpi1.jpg")
duplicate = cv2.imread("rpi2.jpg")
if original.shape == duplicate.shape:
print("The images have same size and channels")
difference = cv2.subtract(original, duplicate)
b, g, r = cv2.split(difference)
if cv2.countNonZero(b) == 0 and cv2.countNonZero(g) == 0 and
cv2.countNonZero(r) == 0:
print("The images are completely Equal")
else:
print("images are different")
There seems to be something strange going on in this loop. I tried to debug it, and I have no explanation for what is going on.
This code is from another Stack Overflow post, and I made some edits to it.
modelImages = ['/home/lie/Desktop/dylan.jpg','/home/lie/Desktop/melissa.jpg']
for modelImage in modelImages:
**print modelImage**
template=cv2.imread(modelImage)
templateg = cv2.cvtColor(template,cv2.COLOR_BGR2GRAY)
keys = surf.detect(templateg)
keys,desc = surfDescriptorExtractor.compute(templateg, keys)
count = 0
for h,des in enumerate(desc):
des = np.array(des,np.float32).reshape((1,64))
retval, results, neigh_resp, dists = knn.find_nearest(des,1)
res,dist = int(results[0][0]),dists[0][0]
if dist<0.1: # draw matched keypoints in red color
count=count + 1
print "space"**
The important parts have asterisks. This is a portion of the code that was suppose to identify similarities among images of faces. What the code does is not important. The strange part is that this loop is executing 1 time for an array of size two.
The output is:
/home/lie/Desktop/dylan.jpg
/home/lie/Desktop/melissa.jpg
space
Notice that both strings in modelImages are printed before space. By the way this is part of a function that is called from a loop. This seems to be more of a python issue than an opencv issue. It almost seems like there is a hidden continue statment
Thanks