Grayscale image segmentation - python

I'm trying to segment a grayscale picture generated from field measurements, that is why it is not a conventional 3-channel picture.
I have tried this piece of code:
import cv2 #this is the openCV library
import numpy as np
# some code to generate img
ret,thresh = cv2.threshold(img ,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
And it spits out this error:
cv2.error: ..\..\..\modules\imgproc\src\thresh.cpp:719: error: (-215) src.type() == CV_8UC1 in function cv::threshold
I have no idea on how to solve this since the usage seems to be pretty straight forward, so any idea is welcome.

The error is due to the following assert statement CV_Assert( src.type() == CV_8UC1 ); in thresh.cpp, meaning your input image is not of type CV_8UC1.
So make sure that your generated input image img is in fact CV_8UC1 (one channel 8-bit image).

So indeed the problem is the image type, since it contains double values thay need to be normalized to 0 ~ 255.
in my case 1000 is the maximum value possible
img = cv2.convertScaleAbs(img / 1000.0 * 255)
This worked for me.

Related

Displaying Tiff images in ipynb or jupyter notebook

I am trying to visualize a tiff image in an ipython notebook using the following code, import statements are ignored for clarity purposes.
from PIL import Image
orig_img_path = os.path.join("path/to/tiff/0.tiff")
img_orig = Image.open(orig_img_path,"r")
plt.imshow(img_orig)
plt.show()
The above snippet just shows me the following black image -
I know that the image pixel values are non-zero since I can open the original images on my MacBook and they look like the following -
I also double check that the pixel values are nonzero by using the following code of casting the PIL image to an np array using the following code and printing the array out -
img_arr = np.array(img_orig)
print(img_arr)
which gives me the following output -
I think I know what the issue is as well - that the matplotlib pyplot thinks that this is a PNG image or something like that and as we can see the pixel values are very small to be perceivable by the human eyes. I mean I can simply multiply the image by 255 which gives the following image as expected, although scaling by 255 is not entirely right since the pixel values need to be normalized for the minimum to corrspond to 0 and max to 255 assuming mat plot lib thinks that it is showing a PNG image -
I would like to know if there is a better way of doing so rather than me manually doing it all the time, any native way of displaying tiff in a Jupyter/ipython notebook which preserves all the good properties of tiff images such as floating point numbers etc.
Thanks and please let me know if anything is unclear.
Edit 1: Link to the original file is here - https://drive.google.com/file/d/1O1-QM6aeU5-QZhT36vOMjDND2vkZNgqB/view?usp=sharing
-- Megh
If you share your original image in .tiff format the solution might be more precise.
You are reading the image pixels as type float: 0-1, and after that, you parse them as uint8 : 0-255 which will turn all pixels values into 0 or 1: Black or almost Black
You can try the following approach to read your image (supposedly Black and White) and parse it:
import cv2
gray = cv2.imread("path/to/tiff/0.tiff", cv2.IMREAD_UNCHANGED)
cv2.namedWindow("MyImage", cv2.WINDOW_NORMAL)
cv2.imshow("MyImage", gray)
cv2.waitKey(0)
What is the range of values that you expect in that image? Did you do any preprocessing to it?
The image you are trying to display in matplotlib contains negative values. Visualizing works well for any kind of uint8 data (Grayscale and RGB) and data in the range of 0 - 1. Your displaying issue can be addressed by adding the min value of the image and then dividing by the max value (effectively normalizing your data to the range 0-1).
[...]
img = np.array(img_orig, dtype=float)
img += abs(np.min(img))
img /= np.max(img)
plt.imshow(img)
plt.show()

Laplacian opencv fails with cv2.error: OpenCV(4.1.2)

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()

OpenCV Error: (-215:Assertion failed) VScn::contains(scn) && VDcn::contains(dcn) && VDepth::contains(depth) in function 'CvtHelper'

Traceback (most recent call last):
File "demo.py", line 132, in
`result = find_strawberry(image)`
File "demo.py", line 63, in find_strawberry
`image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)`
cv2.error: OpenCV(3.4.2) /Users/travis/build/skvark/opencv-python/opencv/modules/imgproc/src/color.hpp:253: error: (-215:Assertion failed) VScn::contains(scn) && VDcn::contains(dcn) && VDepth::contains(depth) in function 'CvtHelper'
I personally have spent a lot of time on this question, hence thought relevant to post it on Stackoverflow.
Question taken from: llSourcell/Object_Detection_demo_LIVE
Even I had the same problem, and the solution was quiet easy. Remember 1 thing, if the RGB values of your image lie in the range of 0-255, make sure the values are not of data type 'float'. As OpenCV considers float only when values range from 0-1. If it finds a float value larger than 1 it clips off the value thinking floats only exists between 0-1. Hence such errors generated. So convert the data type to uint8 if values are from 0-255.
image = image.astype('uint8')
Check this Kaggle Kernel to learn more about it
Just in case if anyone is still having the same error even after applying the above fix then do check the depth of your image i.e. Check whether the image is grayscale or colored since cv2.COLOR_BGR2GRAY cannot convert images that are already grayscale and thus throws up this error.
Well I was doing the Epipolar Geometry (find the link below) and I had this issue. I solved this error by doing one of the two methods:
First method - keeping the original colors:
A. I load the image with its original color (in my case it was RGB) by deleting the zero parameter from cv2.imread.
img1 = cv2.imread('image.jpg')
B. You might need to edit the shape of the image since it is RGB
r, c,_ = img1.shape
C. Comment the conversion
# img1 = cv2.cvtColor(img1,cv2.COLOR_GRAY2BGR)
The second method - converting into grayscale image:
A. I load the image in BGR by adding the zero parameter into cv2.imread.
img1 = cv2.imread('image.jpg',0)
B. You might need to edit the shape of the image since it is BGR
r, c = img1.shape
C. Now you can convert the image into grayscale image
img1 = cv2.cvtColor(img1,cv2.COLOR_GRAY2BGR)
If the two methods do not work for you, you might need to check the links below they might have answer your question:
https://github.com/aleju/imgaug/issues/157
https://github.com/llSourcell/Object_Detection_demo_LIVE/issues/6
Epipolar Geometry
https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_calib3d/py_epipolar_geometry/py_epipolar_geometry.html
get the same error while using trackbar in opencv but this method resolved it:
img = np.full((512,512,3), 12, np.uint8)
where img is your image

(scikit-image) HOG visualization image appears black when saved

I am new to computer vision and image processing and am using this code
from skimage.feature import hog
hog_list, hog_img = hog(test_img_gray,
orientations=8,
pixels_per_cell=(16, 16), cells_per_block=(1, 1),
block_norm='L1',
visualise=True,
feature_vector=True)
plt.figure(figsize=(15,10))
plt.imshow(hog_img)
to get this HOG visualization image
I have 2 questions at this point:
When I try to save this image (as a .pdf or .jpg) the resulting image is pure black. Converting this image to PIL format and examining it with
hog_img_pil = Image.fromarray(hog_img)
hog_img_pil.show()
still shows the image as pure black. Why is this happening and how can I fix it?
When I try to run this code
hog_img = cv2.cvtColor(hog_img, cv2.COLOR_BGR2GRAY)
to convert the image to grayscale I get the error error: (-215) depth == CV_8U || depth == CV_16U || depth == CV_32F in function cvtColor. What do I need to do to get this image in grayscale and why would this be happening?
As additional information, running hog_img.shape returns (1632, 1224) which is just the size of the image, which I had initially interpreted to mean that the image is already is already in grayscale (since it appears to be lacking a dimension for color channel). However, when I then tried to run
test_img_bw = cv2.adaptiveThreshold(
src=hog_img,
maxValue=255,
adaptiveMethod=cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
thresholdType=cv2.THRESH_BINARY,
blockSize=115, C=4)
I got the error error: (-215) src.type() == CV_8UC1 in function adaptiveThreshold which this answer seems to indicate means that the image is not in grayscale.
Finally, another bit of useful information is that running print(hog_img.dtype) on the image returns float64.
I will continue to debug, in the meantime
Thanks for any thoughts :)
Inverting the image with hog_img_inv = cv2.bitwise_not(hog_img) and using
plt.figure(figsize=(15,10))
plt.imshow(hog_img_uint8_inv)
showed that the lines were in fact there but are very faint (I've included the image here for comletness, but you can barley see it (but trust me, it's there)). I will have to do some more processing of the image to get the lines more distinguishable.
Running print(hog_img.dtype) showed that the dtype was float64 when (I think) it should have been uint8. I fixed this by running hog_img_uint8 = hog_img.astype(np.uint8) which seems to have fixed the problem with passing the image to other algorithms (eg. cv2.adaptiveThreshold).
If had the same problem. But if you look inside the docu, they also use this code for better visualisation:
# Rescale histogram for better display
hog_image_rescaled = exposure.rescale_intensity(hog_image, in_range=(0, 0.02))
But I still have the same problem. Visualisation with matplotlib is no problem. saving the image with opencv (or skimage) saves only a black image...

resizing a picture in opencv?

i am writing a face dection program in opencv. And this is the error code below:
result = img[rects[0]:rects[1], rects[2]:rects[3]]
result = cv2.resize(result, (100,100))
img is our original picture and the first step is croping out our rigion of interest into result.
The second step is resize to 100*100 pixels.
the error is:
result = cv2.resize(result, (100,100))
error: ..\..\..\src\opencv\modules\imgproc\src\imgwarp.cpp:1725: error: (-215) ssize.area() > 0
Hope someone can help me. Thanks a lot.
Had the same error in python ,found that image was empty so check whether imread worked or not by using imshow or checking it for NULL then use cv2.resize .

Categories