Alternative to .dilate() OpenCV - python

I am using cv2 and Pillow in my script:
image = Image.open("img1.png")
#do some stuff to the image
image.save("result1.png")
image = cv2.imread("result1.png")
kernel = np.ones((5, 5), np.uint8)
dilated_image = cv2.dilate(image, kernel, iterations=3)
cv2.imwrite("result2.png", dilated_image)
final_image = Image.open("result2.png")
#do some other stuff to the image
final_image.save("final_result.png")
As you can see, I have to switch between OpenCV and Pillow, and save three images. What I want, is to save just one result, instead of three.
Is there a way, where I can continue with Pillow, dilate the image with almost the same execution speed, without using cv2?
I have already tried image.filter(ImageFilter.MaxFilter(size=3)), but it takes too much CPU time. The reason it takes too much time, is that for having the same effect as cv2.dilate(image, kernel, iterations=5), I should use at least image.filter(ImageFilter.MaxFilter(size=15))

If you are just looking for an OpenCV alternative for the function which is there in a standard library, then you can try SciPy's function (SO Question here)

Related

Use opencv in python with gpu support to rotate images

I have compiled opencv 4.6.0 from source files with the cuda support. I have followed the guide for windows 10
The process is completed and I can see my gpu. I want to rotate an image by using GPU. In other words I have this simple code
import cv2
img = cv2.imread("cat.3.jpg")
a = cv2.rotate(img, cv2.ROTATE_90_CLOCKWISE)
cv2.imshow("cat", a)
cv2.waitKey(0)
It works fine, but on CPU. I want a similar code in Python that runs on GPU. A similar solution presented here
for C++.
I have found the solution. This is the code that I have developed
import cv2
import cv2.cuda as cuda
image = cv2.imread("myimage.jpg")
# Storing the image on GPU
src = cv2.cuda_GpuMat()
src.upload(image)
# Applying the rotation
a = cv2.cuda.rotate(src=src, dsize = (414,500), angle = 12, xShift= 0, yShift=0, interpolation=cv2.INTER_NEAREST)
# Downloading the image from GPU and visualizing the image
result = a.download()
cv2.imshow("cat", result)
cv2.waitKey(0)

cv2.imshow won't work after running cv.2 SelectROI

I have a problem here during cropping and saving image by using opencv.
I'm trying to crop by using cv2.SelectROI function but after I drag on the image, cv.2imshow won't work properly.
Here's my code:
import cv2, numpy as np
img = cv2.imread('C:/git/ML/Image/colorful.jpg')
x,y,w,h = cv2.selectROI('img', img, False)
if w and h:
roi = img[y:y+h, x:x+w]
cv2.imshow('cropped', roi)
cv2.moveWindow('cropped', 0, 0)
cv2.imwrite('cropped2.jpg',roi)
cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
print(x,y,w,h)
I've tried to change directory in various ways, put imshow method just before selectROI but none of them worked so far.
cv2.imshow itself shouldn't be a problem because when I don't use selectROI and just manually code the cropping performance from start to finish(by defining mouseleftbutton click, drag, leftbuttonup one by one), cv2.imshow, cv2.movewindow and cv2.imwrite works just fine.
also, not confident that the code itself have interal problem because in other computer, those activities(dragging, cropping, open in new window, save) seems to be working just fine.
is there a possibility that i haven't installed sth that should be needed in order to run selectROI..?
Anyways.. any comments will be much appreciated. Plz help me.

reproduce same output with scikit-image resize and OpenCV resize function

I'm trying to reproduce the same output with these snippets:
Scikit-Image + Keras
from keras.models import model_from_json
import numpy as np
from skimage.io import imread
from skimage.transform import resize
image = resize(imread(img_path, as_grey=False), (80, 80), preserve_range=True, mode='constant')
image /= 255.
img_array = np.array([image])
pred_IN = model.predict(img_array)
OpenCV
import cv2
model = cv2.dnn.readNet('mynet.prototxt', 'mynet.caffemodel')
image = cv2.imread(image_path)
img = cv2.dnn.blobFromImage(image, scalefactor=(1.0/255.0), size=(80, 80), swapRB=True, crop=False)
model.setInput(img)
pred = model.forward()
The problem is that I cannot get the same data to pass to the network (DNN module in case of OpenCV). Network is the same, input data is the same, but the results is slightly different and the reason is that resize function behaves differently between scikit-learn and OpenCV (used internally by blobFromImage) and don't know how to adapt the OpenCV code to match scikit-learn.
My final application will use OpenCV in C++, so I need to match this snippets, as my network has been trained with data generated by scikit-learn.
I think the reason is skimage use antialiasing (gaussian blur from scipy.ndimage before rescale) by default. You can achieve similar result wit resize in OpenCV by blurring your image (e.g. using cv2.GaussianBlur) before cv2.resize. Result from resize is not the same but with proper blur kernel size is very very similar (almost identical). Hope it'll help :)

OpenCV's waitKey() alternative in IPython Notebook

I'm trying to show images with cv2 library in my Jupiter Notebook with cv2.imshow(img) and it shows as expected, but I can not use or don't know how to use cv2.waitKey(0), hence the cell will not stop executing.
cv2.waitKey(0) works in script, but not in Notebook.
Here's a snippet:
cv2.imshow('Image', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
How do I stop executing cell without restarting the whole kernel?
So, thanks to #Micka, here's the solution:
You must write cv2.startWindowThread() first, explained here.
I found the answer from primoz very useful. Here is a code for a function that reads an image from specified path, draws the image, waits for any input to close a window and returns the image object.
import cv2
def cv2_imshow(path, title):
"""
function:
- reads image from `path`,
- shows image in a separate window,
- waits for any key to close the window.
return: image object
"""
img = cv2.imread(path)
cv2.startWindowThread()
cv2.imshow(title, img)
cv2.waitKey(0)
cv2.destroyAllWindows()
return img
Call the function with image path and title:
img_raw = cv2_imshow(path = r'img\example\test.png', title = "raw image")
I have just developed a library to facilitate the opencv functionality in Jupyter.
I used buttons in jupyter for simulating waitKey
It shows the image in the jupyer.
Document
Installation
pip install opencv_jupyter_ui
Usage
You need to only change cv2 to jcv2.
import opencv_jupyter_ui as jcv2
...
jcv2.imshow(img,title)
if jcv2.waitKey(1000)==ord('q'):
break
jcv2.destroyAllWindows()

Why doesn't cv2 dilate actually affect my image?

So, I'm generating a binary (well, really gray scale, 8bit, used as binary) image with python and opencv2, writing a small number of polygons to the image, and then dilating the image using a kernel. However, my source and destination image always end up the same, no matter what kernel I use. Any thoughts?
from matplotlib import pyplot
import numpy as np
import cv2
binary_image = np.zeros(image.shape,dtype='int8')
for rect in list_of_rectangles:
cv2.fillConvexPoly(binary_image, np.array(rect), 255)
kernel = np.ones((11,11),'int')
dilated = cv2.dilate(binary_image,kernel)
if np.array_equal(dilated, binary_image):
print("EPIC FAIL!!")
else:
print("eureka!!")
All I get is EPIC FAIL!
Thanks!
So, it turns out the problem was in the creation of both the kernel and the image. I believe that openCV expects 'uint8' as a data type for both the kernel and the image. In this particular case, I created the kernel with dtype='int', which defaults to 'int64'. Additionally, I created the image as 'int8', not 'uint8'. Somehow this did not trigger an exception, but caused the dilation to fail in a surprising fashion.
Changing the above two lines to
binary_image = np.zeros(image.shape,dtype='uint8')
kernel = np.ones((11,11),'uint8')
Fixed the problem, and now I get EUREKA! Hooray!

Categories

Resources