I am using Haralick textures for a medical image classification problem. I want to iterate through a test folder with unlabeled images and print them in a jupyter notebook with prediction labels.
cv2.imshow() will output a random image to display, however, when I use plt.imshow() to display in a jupyter notebook the same image is returned.
# loop over the test images
test_path = 'data/test/test'
for file in glob.glob(test_path + "/*.jpeg"):
# read the input image
image = cv2.imread(file)
# convert to grayscale
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# extract haralick texture from the image
features = extract_features(gray)
# evaluate the model and predict label
prediction = clf_svm.predict(features.reshape(1, -1))[0]
# show the label
cv2.putText(image, prediction, (20,30), cv2.FONT_HERSHEY_SIMPLEX, 1.0, (0,255,255), 3)
# display the output image
#cv2.imshow("Test_Image", image)
#cv2.waitKey(0)
# display the output image in notebook
plt.imshow(image)
plt.show()
Using pyplot the same image is returned, I would like to return all (or a random subset) of images from the test folder.
If anything is not clear, I will clarify. Thank you.
example image
The core issue is your loop. You're not tabulating during your loop - you're using one single variable. The final item accessed by the loop will the the one that image, gray, and features are all based upon.
The additional processing is then done outside of the loop on these single items, as is the output.
You'll either want to bring all the processing inside your for loop, or you'll want to store your items in a list of some sort and then do further processing on the loop items, possibly with a pause to see different outputs.
Related
I'm very new to programming and in this code I want to apply several filter to images from the "dataFromVid" directory. Instead, I'm getting valueErrors for line 11. (np.hstack)
This is the code :
directory = "/content/dataFromVid/"
for filename in os.listdir(directory):
if filename.endswith(".jpg"): # Check for image files
# Read the image
img = cv2.imread(directory + filename)
# Apply grayscale filter
gray = grayscale_filtre(img)
monochrome = monochrome_filtre(img, 100)
borderDetection = detectEdge(img)
stacked = np.hstack((img, gray, monochrome, borderDetection))
# Show the stacked image
cv2_imshow(stacked)
# Save the grayscale image
cv2.imwrite(directory + "gray_" + filename, gray)
This is the error messages :
Error message
I think that it is something to do with the color channels as I'm trying to put a grayscale filter onto a color image as my first step. But again, I'm a beginner so I'm not too sure. Thanks for any help or comments :))
The ValueError you are getting is most likely due to the fact that the input arrays to np.hstack do not have the same shape along the horizontal axis.
You are trying to horizontally stack four images. If any of these images have a different shape along the horizontal axis, you will get a ValueError.
To fix this issue, you can try resizing all images to have the same width before stacking them. For example, using cv2.resize.
I have been learning how to implement pretrained yolo using pytorch, and I want to display the output image using openCV's cv2.imshow() method.
The output image can be displayed using .show() function and saved using .save() function, I however want to display it using cv2.imshow(), and for that I would need the image in the form of a numpy array.
I'm unaware about how we do that or even if that is at all possible.
Here's the code for it.
import torch
model = torch.hub.load('ultralytics/yolov5', 'yolov5s', pretrained=True)
imgs = ['img.png'] # batch of images
results = model(imgs)
results.print()
results.show() # or .save(), shows/saves the same image with bounding boxes around detected objects
# Show 'results' using openCV's cv2.imshow() method?
results.xyxy[0] # img1 predictions (tensor)
print(results.pandas().xyxy[0]) # img1 predictions (pandas)
A longer way of solving this problem would be to create bounding boxes ourselves over the detected objects in the image and display it, but consider me lazy :p .
I am lazy like you :) and you can display the bounding boxes without the need to draw them manually. When you call results.save() it will save a version of the image with the boxes to this folder 'runs/detect/exp/' Then you can display that image using cv2.
results.save()
import cv2
img = cv2.imread("runs/detect/exp/zidane.jpg")
#cv2.imgshow does not work on Google collab so this is a work around.
# You should get the same results if you use cv2.imgshow
from google.colab.patches import cv2_imshow
cv2_imshow(img)
had the same issue, so I wrote a small method to do so quickly draw the image without saving it.
def drawRectangles(image, dfResults):
for index, row in dfResults.iterrows():
print( (row['xmin'], row['ymin']))
image = cv2.rectangle(image, (row['xmin'], row['ymin']), (row['xmax'], row['ymax']), (255, 0, 0), 2)
cv2_imshow(image)
_
results = model(image)
dfResults = results.pandas().xyxy[0]
self.drawRectangles(image, dfResults[['xmin', 'ymin', 'xmax','ymax']].astype(int))
Just open the image via cv2 and then ad rectangles by drawing a rectangle via the given points from your result arrays?
import cv2
img = cv2.imread("image_path")
link how to draw a rectangle with cv2
#ChristophRackwitz
here u have it
cv2.rectangle(image, start_point, end_point, color, thickness)
I am trying to crop an image of a piece of card/paper or such so that the card/paper is in focus. I tried the below code but the problem is that it works only when the object in question is alone in the picture. If it is a blank background with nothing else in it- the cropping is flawless, otherwise it does not work as expected.
I am attempting create a system which crops different kinds of images and puts them through a classifier and then extracts text from them.
import cv2
import numpy as np
filenames = "img.jpg"
img = cv2.imread(filenames)
blurred = cv2.blur(img, (3,3))
canny = cv2.Canny(blurred, 50, 200)
## find the non-zero min-max coords of canny
pts = np.argwhere(canny>0)
y1,x1 = pts.min(axis=0)
y2,x2 = pts.max(axis=0)
## crop the region
cropped = img[y1:y2, x1:x2]
filename_cropped = filenames.split('.')
filename_cropped[0] = filename_cropped[0] + '_cropped'
filename_cropped = '.'.join(filename_cropped)
cv2.imwrite(filename_cropped, cropped)
An sample image that works is
Something that does not work is
Can anyone help with this?
The first image works because the entire images besides your target is empty. Canny will also give other results when there is more in the image.
If you are looking for those specific cards I suggest you try to use some colour filtering first. You can try to filer for the blue/purple hue of the card.
Increasing the canny threshold could also work, but you will always still be finding the hand as well in this image unless you add some colour filtering.
You can also try Sobel edge detection . This will probably highlight the instant edges of the card pretty well. But then again, it will also show the hand, so you can't just take all the Sobel/Canny outputs. You need to add processing before it that isolates the card, or after it that can find the rectangular shape of the card in the sobel/canny.
I am trying to train my model for image segmentation task and for that i am using a generator to yield the dataset. i have trained it multiple times before but recently I am facing this error.
ValueError:'generator' yielded an element of shape (128,192,3) where an element of shape (128,192,1) was expected.
when i printed out the shapes of my image and mask that comes out of generator it shows.
image:(128,192,1)
mask:(128,192,3)
The generator element gets both the image and mask data loaded from the tensorflow dataset. The question is how does the shape of the mask of an grayscale image changes to 3 when even the input image is grayscale of 1?
How to possibly convert the mask back to channel of 1?
Unfortunately I cannot post the complete code to reproduce as its under privacy
Without knowing more of the library you're using for reading the image it's hard to know. I am assuming you're using PIL and I'll do
from PIL import Image
img = Image.open('im1.jpg','r')
img = img.convert('L')
'L' is for the grayscale, you can check more mode -> https://pillow.readthedocs.io/en/stable/handbook/concepts.html
While you're updating your code, you should check the preprocessing module of keras, then the code will be
# Returns a PIL image
image = tf.keras.preprocessing.image.load_img(image_path, color_mode="grayscale")
input_arr = keras.preprocessing.image.img_to_array(image)
input_arr = np.array([input_arr]) # Convert single image to a batch.
predictions = model.predict(input_arr)
More information -> https://www.tensorflow.org/api_docs/python/tf/keras/preprocessing/image/load_img
I'm writing a script in Python for my image processing class, which should read a directory for images, display them, and then I will eventually add additional code to perform Otsu thresholding on these images. I can get a reference image to display properly to include Otsu thresholding; however, I run into trouble when I attempt to display the remaining images in the directory. I am not sure that my images are being read from the directory correctly, as I am trying to store them in an array; however, I can see the output window displays grey squares which correspond to the dimensions of the actual image resolutions, which suggests that they are being at least partly read correctly.
I've already attempted to isolate the script to load images and display them into a separate file and running it. I was concerned that the successful processing of my sample image (which included a black/white binarization) was somehow affecting my image display later. This was not the case, as running a separate script produced the same grey square output.
****Update****
I've managed to tweak the below script(not yet updated) to run almost correctly. By writing the full filepath directly for each file, I can get the output to display correctly. It appears there is some issue with loading images into an array, best I can tell; a potential workaround for future testing is importing file locations as a string array, and implementing that vs. loading images into an array directly.
import cv2 as cv
import numpy as np
from PIL import Image
import glob
from matplotlib import pyplot as plot
import time
image=cv.imread('Fig ref.jpg')
image2=cv.cvtColor(image, cv.COLOR_RGB2GRAY)
cv.imshow('Image', image)
# global thresholding
ret1,th1 = cv.threshold(image2,127,255,cv.THRESH_BINARY)
# Otsu's thresholding
ret2,th2 = cv.threshold(image2,0,255,cv.THRESH_BINARY+cv.THRESH_OTSU)
# Otsu's thresholding after Gaussian filtering
blur = cv.GaussianBlur(image2,(5,5),0)
ret3,th3 = cv.threshold(blur,0,255,cv.THRESH_BINARY+cv.THRESH_OTSU)
# plot all the images and their histograms
images = [image2, 0, th1,
image2, 0, th2,
blur, 0, th3]
titles = ['Original Noisy Image','Histogram','Global Thresholding (v=127)',
'Original Noisy Image','Histogram',"Otsu's Thresholding",
'Gaussian filtered Image','Histogram',"Otsu's Thresholding"]
for i in range(3):
plot.subplot(3,3,i*3+1),plot.imshow(images[i*3],'gray')
plot.title(titles[i*3]), plot.xticks([]), plot.yticks([])
plot.subplot(3,3,i*3+2),plot.hist(images[i*3].ravel(),256)
plot.title(titles[i*3+1]), plot.xticks([]), plot.yticks([])
plot.subplot(3,3,i*3+3),plot.imshow(images[i*3+2],'gray')
plot.title(titles[i*3+2]), plot.xticks([]), plot.yticks([])
plot.show()
imageFolderPath = 'D:\Google Drive\Engineering\Senior Year\Image processing\Image processing group work'
imagePath = glob.glob(imageFolderPath + '/*.JPG')
im_array = np.array( [np.array(Image.open(img).convert('RGB')) for img in imagePath] )
temp=cv.imread("D:\Google Drive\Engineering\Senior Year\Image processing\Image processing group work\Fig ref.jpg")
cv.imshow('image', temp)
time.sleep(15)
for i in range(9):
cv.imshow('Image', im_array[i])
time.sleep(2)
plot.subplot(3,3,i*3+3),plot.imshow(images[i*3+2],'gray'): The second argument says you use gray color map. Get rid of it and you would get color displays.