I am trying to apply laplacian to a median filter output to get a sharper image, by later processing. The code snippet is as below :
img = plt.imread('example.png')
img_res = cv.resize(img,(256,256))
gray_image = cv.cvtColor(img_res, cv.COLOR_BGR2GRAY)
median_img = median_filter(gray_image, 5)
# Calculate the Laplacian
lap_img = cv.Laplacian(median_img,cv.CV_64F)
The input image is a RGB medical image. I am faced with the following error, when running this code:
cv2.error: OpenCV(4.1.2) C:/projects/opencv-python/opencv/modules/imgproc/src/filter.simd.hpp:3175: error: (-213:The function/feature is not implemented) Unsupported combination of source format (=5), and destination format (=6) in function 'cv::opt_AVX2::getLinearFilter'
This error occurs for any image from the dataset. Could you please point out what could be the issue? The example is followed from this link for grayscale images.
Instead of using two different libraries (matplotlib and opencv), stick to using one library at a time while performing image-processing. The reason is because these two libraries use different formats to store images. matplotlib uses RGB convention while opencv uses BGR. My guess is that you're encountering this error due to using matplotlib to load the image, and then performing operations with opencv. Simply, loading the image using cv2.imread() instead of plt.imread() seems to fix the problem
Input -> Output
import cv2
from scipy.ndimage.filters import median_filter
import numpy as np
img = cv2.imread('1.png')
gray_image = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
median_img = median_filter(gray_image, 5)
# Calculate the Laplacian
lap_img = cv2.Laplacian(median_img,cv2.CV_64F).astype(np.uint8)
cv2.imshow('lap_img', lap_img)
cv2.imwrite('lap_img.png', lap_img)
cv2.waitKey()
Related
I want to change the img_path to the frames generated from opencv:
img = image.load_img(img_path, target_size=(224, 224))
How can I rewrite it?
I am assuming that the image.load_img() function that you are using is the one from keras_utils package.
As it is noted in the documentation, load_img() accepts path to the image as the first parameter and returns:
Returns:
A PIL Image instance.
It is not mentioned in the question, but if you read the frames from the camera using opencv they should already be numpy arrays which you could to pass to your model. Of course you should resize them to (224,224) before (how to resize the image using opencv).
However, if you want to have the PIL images (to have the same type as the one returned by load_img()), you need to convert your opencv frames (numpy array) to PIL image. Follow this question and answer by #ZdaR to do this conversion:
import cv2
import numpy as np
from PIL import Image
img = cv2.imread("path/to/img.png")
# You may need to convert the color.
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
im_pil = Image.fromarray(img)
# For reversing the operation:
im_np = np.asarray(im_pil)
I used Zbar and OpenCV to read the QR code in the image below but both failed to detect it. For ZBar, I use pyzbar library as the python wrapper. There are images that QR is detected correctly and images really similar to the successful ones that fail. My phone camera can read the QR code in the uploaded image which means it is a valid one. Below is the code snippet:
from pyzbar.pyzbar import decode
from pyzbar.pyzbar import ZBarSymbol
import cv2
# zbar
results = decode(cv2.imread(image_path), symbols=[ZBarSymbol.QRCODE])
print(results)
# opencv
qr_decoder = cv2.QRCodeDetector()
data, bbox, rectified_image = qr_decoder.detectAndDecode(cv2.imread(image_path))
print(data, bbox)
What type of pre-processing will help to increase the rate of success for detecting QR codes?
zbar, which does some preprocessing, does not detect the QR code, which you can test running zbarimg image.jpg.
Good binarization is useful here. I got this to work using the kraken.binarization.nlbin() function of the Kraken library. The library is for OCR, but works very well for QR codes, too, by using non-linear processing. The Kraken binarization code is here.
Here is the code for the sample:
from kraken import binarization
from PIL import Image
from pyzbar.pyzbar import decode
from pyzbar.pyzbar import ZBarSymbol
image_path = "image.jpg"
# binarization using kraken
im = Image.open(image_path)
bw_im = binarization.nlbin(im)
# zbar
decode(bw_im, symbols=[ZBarSymbol.QRCODE])
[Decoded(data=b'DE-AAA002065', type='QRCODE', rect=Rect(left=1429, top=361, width=300, height=306), polygon=[Point(x=1429, y=361), Point(x=1429, y=667), Point(x=1729, y=667), Point(x=1723, y=365)])]
The following picture shows the clear image of the QR code after binarization:
I had a similar issue, and Seanpue's answer got me on the right track for this problem. Since I was already using the OpenCV library for image processing rather than PIL, I used it to perform Otsu's Binarization using the directions in an OpenCV tutorial on Image Thresholding. Here's my code:
import cv2
from pyzbar.pyzbar import decode
from pyzbar.pyzbar import ZBarSymbol
image_path = "qr.jpg"
# preprocessing using opencv
im = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE)
blur = cv2.GaussianBlur(im, (5, 5), 0)
ret, bw_im = cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)
# zbar
decode(bw_im, symbols=[ZBarSymbol.QRCODE])
[Decoded(data=b'DE-AAA002065', type='QRCODE', rect=Rect(left=1429, top=362, width=300, height=305), polygon=[Point(x=1429, y=362), Point(x=1430, y=667), Point(x=1729, y=667), Point(x=1724, y=366)])]
Applying the gaussian blur is supposed to remove noise from the picture to make the binarization more effective, but for my application it didn't actually make much difference. What was vital was to convert the image to grayscale to make the threshold function work (done here by opening the file with the cv2.IMREAD_GRAYSCALE flag).
QReader use to work quite well for these cases.
from qreader import QReader
import cv2
if __name__ == '__main__':
# Initialize QReader
detector = QReader()
img = cv2.cvtColor(cv2.imread('92iKG.jpg'), cv2.COLOR_BGR2RGB)
# Detect and Decode the QR
print(detector.detect_and_decode(image=img))
This code output for this QR:
DE-AAA002065
I've tried overlaying two images in openCV both in openCV and in PIL, but to no avail. I'm using a 1000x1000x3 array of np.zeros for the background (aka, a black background) and this random image of my monitor, but I really can't get it to work for some reason unbeknownst to me.
Trying with OpenCV only: (result(if you pay attention, you can see a couple of weird lines and dots in the middle))
base_temp = np.zeros((1000,1000,3))
foreground_temp = cv2.imread('exampleImageThatILinkedAbove.png')
base_temp[offset_y:offset_y+foreground_temp.shape[0], offset_x:offset_x+foreground_temp.shape[1]] = foreground_temp
Trying with PIL: (The result is literally the same as the OpenCV version)
base_temp = cv2.convertScaleAbs(self.base) #Convert to uint8 for cvtColor
base_temp = cv2.cvtColor(base_temp, cv2.COLOR_BGR2RGB) #PIL uses RGB and OpenCV uses BGR
base_temp = Image.fromarray(base_temp) #Convert to PIL Image
foreground_temp = cv2.cvtColor(cv2.convertScaleAbs(self.last_img), cv2.COLOR_BGR2RGB)
foreground_temp = Image.fromarray(foreground_temp)
base_temp.paste(foreground_temp, offset)
I'm using python3.5 and and OpenCV3.4 on Windows 10, if that's any help.
I'd like to avoid any solutions that require saving the cv2 images and then reloading them in another module to convert them but if it's unavoidable that's okay too. Any help would be appreciated!
If you check the type of base_temp, you will see it is float64 and that is going to cause you problems when you try to save it as a JPEG which expects unsigned 8-bit values.
So the solution is to create your base_temp image with the correct type:
base_temp = np.zeros((1000,1000,3), dtype=np.uint8)
The complete code and result look like this:
import cv2
import numpy as np
from PIL import Image
# Make black background - not square, so it shows up problems with swapped dimensions
base_temp=np.zeros((768,1024,3),dtype=np.uint8)
foreground_temp=cv2.imread('monitor.png')
# Paste with different x and y offsets so it is clear when indices are swapped
offset_y=80
offset_x=40
base_temp[offset_y:offset_y+foreground_temp.shape[0], offset_x:offset_x+foreground_temp.shape[1]] = foreground_temp
Image.fromarray(base_temp).save('result.png')
I am trying to detect humans in images using the haarcascade full body algorithm using OpenCv in Python.
when i consider using it on a single image, I face no issues.
import numpy as np
import cv2 as cv
body_cascade = cv.CascadeClassifier(r'...\haarcascade_fullbody.xml')
image = cv.imread(r'...\image.jpg')
gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
body = body_cascade.detectMultiScale(gray, 1.01, 4)
for (x,y,w,h) in body:
cv.rectangle(image,(x,y),(x+w,y+h),(255,0,0),3)
But, when I try to use the same program and iterate over several images at once, I get a cryptic OpenCv error. I have some images in a folder and I want to separate images with humans in them from those that don't. I wrote the following:
import os
for file in os.walk(r'...\Folder'):
file=str(file)
im=cv.imread(file)
gray = cv.cvtColor(im, cv.COLOR_BGR2GRAY)
body = body_cascade.detectMultiScale(gray, 1.01, 4)
for (x,y,w,h) in body:
cv.rectangle(im,(x,y),(x+w,y+h),(255,0,0),3)
if(body.size >= 0):
print('okay')
else:
print('Not okay')
But I get the following error :
error: OpenCV(3.4.2) c:\projects\opencv-python\opencv\modules\imgproc\src\color.hpp:253: error: (-215:Assertion failed) VScn::contains(scn) && VDcn::contains(dcn) && VDepth::contains(depth) in function 'cv::CvtHelper<struct cv::Set<3,4,-1>,struct cv::Set<1,-1,-1>,struct cv::Set<0,2,5>,2>::CvtHelper'
for the line gray = cv.cvtColor(im, cv.COLOR_BGR2GRAY)
I am unable to understand what the error is and why the same code that works when taking individual images is working but not the case when iterating through a folder. Do I need to resize the images ?
Also, I tried with keeping just one image in the folder, on which the code had worked before, still doesn't work.
Doc, it seems like OpenCV fails to locate the image. What happens if you're using full paths instead of relative ones? (and what are the three dots there "..." ?)
please dump the file that you read back to disc for debugging purposes and I think you'll be surprised.
I am trying to stack two images together, so i can show both in a single window.
First image is the original, 3-channel image, second one is a gray version.
I did the color conversion with cv2.cvtColor, transformed back to 3-channel with numpy.dstack,
and when i try cv2.imshow, it gives me a "core dumped" error.
Am i missing something? I need both images to have the same number of channels to stack them
with numpy.hstack. This happens on a Ubuntu 64bit machine.
import cv2
import numpy as np
img = cv2.imread("/home/bernie/Dropbox/Python/Opencv/lena512.jpg")
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
gray = np.dstack((gray,gray,gray))
#res = np.hstack((img,gray))
print gray.dtype
print gray.shape
cv2.imshow('gray',gray)
#cv2.imshow('res',res)
cv2.waitKey()
addition
On the other hand, using
gray = cv2.cvtColor(gray,cv2.COLOR_GRAY2BGR)
in line 7 works without complaints, so i will stick to this for now. This means that there is a difference
between
the cv2.cvtColor result and numpy.dstack result for turning a 1-channel image to 3-channel with equal values.
As suggested in the comments, try using cv2.merge since apparently it's strided differently from np.dstack:
gray = cv2.merge([gray]*3)
See #fraxel's link for more info