I'm attempting to locate a rectangular object by its color, and then find the coordinates of the center of the object, or the borders, I"m not picky about which.
I've been successful in isolating the color and creating a mask, but the findContours function is not working and i think it's because i've not successfully provided a proper bimodal image to findContours.
%matplotlib inline
import matplotlib.image as mpimg
from matplotlib import pyplot as plt
import cv2
import numpy as np
red_image = mpimg.imread('/vagrant/notebooks/red_thing.jpg')
hsv = cv2.cvtColor(red_image, cv2.COLOR_BGR2HSV)
lower_red = np.array([30,150,50])
upper_red = np.array([255,255,180])
mask = cv2.inRange(hsv, lower_red, upper_red)
res = cv2.bitwise_and(red_image,red_image, mask= mask)
kernel = np.ones((20,20),np.uint8)
ret,thresh1 = cv2.threshold(res,60,255,cv2.THRESH_BINARY)
# perform 'open' operation to homogenize object
opened = cv2.morphologyEx(thresh1, cv2.MORPH_OPEN, kernel)
image, contours, hierarchy = cv2.findContours(opened,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
The last line produces the following error, I can't figure out how to resolve this.
---------------------------------------------------------------------------
error Traceback (most recent call last)
<ipython-input-130-06cc5691b64a> in <module>()
----> 1 image, contours, hierarchy = cv2.findContours(opened,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
error: /home/vagrant/opencv/modules/imgproc/src/contours.cpp:199: error: (-210) [Start]FindContours supports only CV_8UC1 images when mode != CV_RETR_FLOODFILL otherwise supports CV_32SC1 images only in function cvStartFindContours_Impl
i was able to fix the error with a conversion to gray, like this: gray = cv2.cvtColor(res, cv2.COLOR_BGR2GRAY)
Related
I'm trying to get the contours of a portion of an image but I keep getting an error when I call the cv.findContour image. To find the object in the image I first try to extract the colour of the object, which is red, then I try to find the contours on the detected objects.
import cv2 as cv
import numpy as np
def main():
image_find_goal = "image.jpg"
kernel = np.ones((5,5),np.uint8)
#findGoal(image_find_goal)
img1 = cv.imread(image_find_goal)
img = cv.resize(img1,(700,700))
hsv = cv.cvtColor(img,cv.COLOR_BGR2HSV)
#range for red color
lower_r = np.array([160,100,100])
upper_r = np.array([179,255,255])
mask = cv.inRange(hsv,lower_r,upper_r)
res = cv.bitwise_and(img,img,mask=mask)
_,thresh = cv.threshold(res,125,255,cv.THRESH_BINARY)
dilate = cv.dilate(thresh,None,iterations=1)
contours, hierarchy = cv.findContours(dilate,cv.RETR_TREE,cv.CHAIN_APPROX_NONE)
for cnt in contours:
epsilon = 0.1*cv.arcLength(cnt,True)
approx = cv.approxPolyDP(cnt,epsilon,True)
if len(approx) == 4:
cv.drawContours(img,cnt,-1,(60,255,255),4)
cv.imshow('OBSTACLES',img)
cv.waitKey(0)
cv.destroyWindow(img)
The error I get is:
contours, hierarchy =
cv.findContours(dilate,cv.RETR_TREE,cv.CHAIN_APPROX_NONE) cv2.error:
OpenCV(4.4.0)
/tmp/pip-req-build-sw_3pm_8/opencv/modules/imgproc/src/contours.cpp:195:
error: (-210:Unsupported format or combination of formats)
[Start]FindContours supports only CV_8UC1 images when mode !=
CV_RETR_FLOODFILL otherwise supports CV_32SC1 images only in function
'cvStartFindContours_Impl'
I think this snippet solves your issue. Since you are interested in Contours I would apply the Canny Edge Detection before dilating. This move will fix also the CV Type error you are getting
import cv2 as cv
import numpy as np
image_find_goal = "image.jpg"
#findGoal(image_find_goal)
img1 = cv.imread(image_find_goal)
img = cv.resize(img1,(700,700))
hsv = cv.cvtColor(img,cv.COLOR_BGR2HSV)
#range for red color
lower_r = np.array([160,100,100])
upper_r = np.array([179,255,255])
mask = cv.inRange(hsv,lower_r,upper_r)
res = cv.bitwise_and(img,img,mask=mask)
_,thresh = cv.threshold(res,125,255,cv.THRESH_BINARY)
# check which are the best canny threshold values for your image
imgCanny = cv.Canny(thresh, 180, 180)
dilate = cv.dilate(imgCanny, None, iterations = 1)
# cv.imshow("dilate", dilate)
# cv.waitKey()
contours, hierarchy = cv.findContours(dilate,cv.RETR_TREE,cv.CHAIN_APPROX_NONE)
for cnt in contours:
epsilon = 0.1*cv.arcLength(cnt,True)
approx = cv.approxPolyDP(cnt,epsilon,True)
if len(approx) == 4:
cv.drawContours(img,cnt,-1,(60,255,255),4)
cv.imshow('OBSTACLES',img)
cv.waitKey(0)
cv.destroyAllWindows()
I am trying to do adaptive thresholding after applying Sobel filtering on an image, as seen in the code below:
import numpy as np
import matplotlib.pyplot as plt
import cv2
image = cv2.imread("train.jpg")
img = np.array(image, dtype=np.uint8)
#convert to greyscale
img_grey = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
#remove noise
img_smooth = cv2.GaussianBlur(img_grey, (13,13), 0)
sobely = cv2.Sobel(img_smooth,cv2.CV_64F,0,1,ksize=9)
thres = cv2.adaptiveThreshold(sobely, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
cv2.THRESH_BINARY, 73, 2)
However, when I try to do adaptive thresholding, I get the following error:
cv2.error: OpenCV(4.1.0) /Users/travis/build/skvark/opencv-
python/opencv/modules/imgproc/src/thresh.cpp:1627: error: (-215:Assertion
failed) src.type() == CV_8UC1 in function 'adaptiveThreshold'
I have read that this error occurs if your image is not greyscale, however, I converted my image to greyscale at the start of the code. I am not sure why I am getting this error. Any insights are appreciated.
What you read is correct, that error actually means that your Mat is not a gray-scale image.
That happens because Sobel is changing the data to cv2.CV_64F (see the second parameter in the documentation here).
So after Sobel you need to convert the image to a gray-scale, you can do that with convertScaleAbs and after that pass it's output to adaptiveThreshold
I am trying opencv with python now.
What mean this error?
OpenCV Error: Assertion failed (m.dims >= 2) in Mat, file /build/opencv-ISmtkH/opencv-2.4.9.1+dfsg/modules/core/src/matrix.cpp, line 269
Traceback (most recent call last):
File "sabun5.py", line 16, in <module>
img_m = cv2.threshold(img_df, 50, 255, cv2.THRESH_BINARY)[1]
cv2.error: /build/opencv-ISmtkH/opencv-2.4.9.1+dfsg/modules/core/src/matrix.cpp:269: error: (-215) m.dims >= 2 in function Mat
You can see in the OpenCV documentation, that the threshold function just allow single-channel images.
If your image is a color one, it won't work. If it's grayscale but you are loading it with imread, it might be possible that OpenCV load it as a 3-channel one. You can add the flag to load it as a single-channel with CV_8UC1 (supposing it is an 8 bit unsigned one, which is the more common for a grayscale image).
For example:
img_df = cv2.imread("image/path", cv2.CV_8UC1)
you have to convert the image into grayscale before thresholding your image has more then two dimentions i.e (height,width,color-channel) gray scale image has only two dimention(height,width)
it might help
import cv2
img = cv.imread('x.png',0)
# where 0 converts the image in grayscale or gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
img_m = cv2.threshold(img, 50, 255, cv2.THRESH_BINARY)[1]
cv2.waitKey(0)
Traceback (most recent call last):
File "C:/Users/michail.gakas/Desktop/python scripts/counters.1py.py", line 10, in
imgray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
error: C:\builds\master_PackSlaveAddon-win64-vc12-static\opencv\modules\imgproc\src\color.cpp:7456: error: (-215) scn == 3 || scn == 4 in function cv::ipp_cvtColor
My code:
import numpy as np
import cv2
img = cv2.imread('star.jpg',0)
imgray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ret,thresh = cv2.threshold(imgray,127,255,0)
im2, contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
#cv2.waitKey(0)
#cv2.destroyAllWindows()
I am using python 2.7 CV3 but i had CV2 installed before
I don't have OpenCV with me right now but from what I see you did
img = cv2.imread("star.jpg", 0)
but what you probably wanted to do is open it in color as:
img = cv2.imread("star.jpg", 1)
or open it "unchanged" as:
img = cv2.imread("star.jpg", -1)
What you did is you opened an image in grayscale mode and then tried to convert it to grayscale. That error actually states that assert didn't find an image with 3 or 4 channels and BGR2GRAYSCALE goes from a color jpg image (3 channels) or a color png image (4 channels, 1 for alpha sometimes) to a 1 channel grayscale image. Alpha channel is discarded in this function. Pls make your life easier and use the official flags cv2 offers for easier code readability.
cv2.IMREAD_UNCHANGED (<0) loads the image as is (including the alpha channel if present)
cv2.IMREAD_GRAYSCALE ( 0) loads the image as an intensity one
cv2.IMREAD_COLOR (>0) loads the image in the RGB format
I'm pretty amateur at image processing. I could successfully do normal thresholding but however I'm facing an error in Adaptive Thresholding.
Here is my code:
import cv2
import numpy as np
img = cv2.imread("vehicle004.jpg")
img = cv2.medianBlur(img,5)
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
_,th2=cv2.adaptiveThreshold(gray,255,cv2.ADAPTIVE_THRESH_MEAN_C,cv2.THRESH_BINARY,11,2)
cv2.imshow("window2",th2)
cv2.waitKey(0)
cv2.destroyAllWindows()
Error Message:
line 7, in <module>
_,th2 = cv2.adaptiveThreshold(gray,255,cv2.ADAPTIVE_THRESH_MEAN_C,cv2.THRESH_BINARY,11,2)
ValueError: too many values to unpack
Any help is appreciated.
As per the documentation, the cv2.adaptiveThreshold() returns only 1 value that is the threshold image and in this case you are trying to receive 2 values from that method, that is why ValueError: too many values to unpack error is raised.
After fixing the issue the code may look like:
import cv2
import numpy as np
img = cv2.imread("vehicle004.jpg")
img = cv2.medianBlur(img,5)
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
th2=cv2.adaptiveThreshold(gray,255,cv2.ADAPTIVE_THRESH_MEAN_C,cv2.THRESH_BINARY,11,2)
cv2.imshow("window2",th2)
cv2.waitKey(0)
cv2.destroyAllWindows()