Kernel dies when running .detector (openCV) - python

I'm currently working on an openCV course through Udemy and have run into the trouble where my kernel is dying. I tried eliminating line by line to see what could the cause, and I found that when the code comes to the line: keypoints = detector.detect(image) it fails. Now I am kind of an amateur when it comes to this kind of stuff, but would appreciate some feedback as to why this could be occurring. Here's the code i'm working with:
import cv2
import numpy as np;
# Read image
image = cv2.imread("images/Sunflowers.jpg")
# Set up the detector with default parameters.
detector = cv2.SimpleBlobDetector()
# Detect blobs.
keypoints = detector.detect(image)
# Draw detected blobs as red circles.
# cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS ensures the size of
# the circle corresponds to the size of blob
blank = np.zeros((1,1))
blobs = cv2.drawKeypoints(image, keypoints, blank, (0,255,255),
cv2.DRAW_MATCHES_FLAGS_DEFAULT)
# Show keypoints
cv2.imshow("Blobs", blobs)
cv2.waitKey(0)
cv2.destroyAllWindows()```

Please replace:
detector = cv2.SimpleBlobDetector()
with:
detector = cv2.SimpleBlobDetector_create()

Related

How can I display an image to me (as an user) and select a section of that image?

I will explain myself better, the point is that I want to develop a code that displays an image to me, then with the mouse as the image is displayed I can select or crop it as I want.
So, for example, as this code does, it would select any section of the image:
from PIL import Image
im = Image.open("test.jpg")
crop_rectangle = (50, 50, 200, 200)
cropped_im = im.crop(crop_rectangle)
cropped_im.show()
That is basically it, all I want is to crop an image at the points or coordinates that I please, I have been searching but can not find any library that helps me to do so.
NOTE: The code I am showing is an answer on this post, in case you want to check it out: How can i select a part of a image using python?
EDIT: Here is something I foud that may help me in a first instance, but is not entirely what I am looking for, it at least lets me find the coordinates that I want from the image - with some modifications on the code - and then I will keep processing the image. By now it is not solving my issue but it is a beginning. --> Using "cv2.setMouseCallback" method
The comments I received from Mark Setchell and bfris enlightened me, one with a C++ code and another one with a recommendation of OpenCV.
But in addition to their comments, I found this article where they explain exactly what I want to do, so I consider my question answered. Select ROI or Multiple ROIs [Bounding box] in OPENCV python.
import cv2
import numpy as np
#image_path
img_path="image.jpeg"
#read image
img_raw = cv2.imread(img_path)
#select ROI function
roi = cv2.selectROI(img_raw)
#print rectangle points of selected roi
print(roi)
#Crop selected roi from raw image
roi_cropped = img_raw[int(roi[1]):int(roi[1]+roi[3]), int(roi[0]):int(roi[0]+roi[2])]
#show cropped image
cv2.imshow("ROI", roi_cropped)
cv2.imwrite("crop.jpeg",roi_cropped)
#hold window
cv2.waitKey(0)
or
import cv2
import numpy as np
#image_path
img_path="image.jpeg"
#read image
img_raw = cv2.imread(img_path)
#select ROIs function
ROIs = cv2.selectROIs("Select Rois",img_raw)
#print rectangle points of selected roi
print(ROIs)
#Crop selected roi ffrom raw image
#counter to save image with different name
crop_number=0
#loop over every bounding box save in array "ROIs"
for rect in ROIs:
x1=rect[0]
y1=rect[1]
x2=rect[2]
y2=rect[3]
#crop roi from original image
img_crop=img_raw[y1:y1+y2,x1:x1+x2]
#show cropped image
cv2.imshow("crop"+str(crop_number),img_crop)
#save cropped image
cv2.imwrite("crop"+str(crop_number)+".jpeg",img_crop)
crop_number+=1
#hold window
cv2.waitKey(0)

Python OpenCV: inRange() stopped working without change

I am currently doing real time object detection of an orange ball with Raspberry Pi 3 Model B. The code below is supposed to take a frame, then with the cv2.inRange() function, filter out the image using RGB (BGR). Then I apply dialation and erosion to remove noise. Then I find the contours and draw them. This code worked until now. However when I ran it today without changing it, I got the folowing error:
Traceback (most recent call last):
File "/home/pi/Desktop/maincode.py", line 12, in <module>
mask = cv2.inRange(frame, lower, upper)
error: /build/opencv-ISmtkH/opencv-2.4.9.1+dfsg/modules/core/src/arithm.cpp:2701: error: (-209) The lower bounary is neither an array of the same size and same type as src, nor a scalar in function inRange
Any help would be really awesome, because I was new to openCV and spent a lot of time proggraming this, and I have a competetion of robotics in 5 days.
Thank you in advance
import cv2
import cv2.cv as cv
import numpy as np
capture = cv2.VideoCapture(0)
while capture.isOpened:
ret, frame = capture.read()
im = frame
lower = np.array([0, 100 ,150], dtype = 'uint8')
upper = np.array([10,180,255], dtype = 'uint8')
mask = cv2.inRange(frame, lower, upper)
eroded = cv2.erode(mask, np.ones((7, 7)))
dilated = cv2.dilate(eroded, np.ones((7, 7)))
contours, hierarchy = cv2.findContours(dilated,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(im,contours,-1,(0,255,0),3)
cv2.imshow('colors',im)
cv2.waitKey(1)
The error you receive almost certainly means you have an empty image (or you mix up the sizes of your input image).
Webcam captures in OpenCV often start with one or a couple of black/emtpy images (crappy drivers). Since it goes too fast, that's why you don't notice this. However, this will have an influence on your application if you want to process the image. Therefore, I recommend you to check the image before proceeding with the calculations on them. Just add this after your capture.read() line:
if ret == True:
Note: make sure (by printing in the console or something) that this only happens when you start capturing. If this happens regularly (empty frames from your webcam), maybe there's something else wrong (or maybe with your webcam). Also check it on another computer.

Blob detection using OpenCV

I am trying to do some white blob detection using OpenCV. But my script failed to detect the big white block which is my goal while some small blobs are detected. I am new to OpenCV, and am i doing something wrong when using simpleblobdetection in OpenCV? [Solved partially, please read below]
And here is the script:
#!/usr/bin/python
# Standard imports
import cv2
import numpy as np;
from matplotlib import pyplot as plt
# Read image
im = cv2.imread('whiteborder.jpg', cv2.IMREAD_GRAYSCALE)
imfiltered = cv2.inRange(im,255,255)
#OPENING
kernel = np.ones((5,5))
opening = cv2.morphologyEx(imfiltered,cv2.MORPH_OPEN,kernel)
#write out the filtered image
cv2.imwrite('colorfiltered.jpg',opening)
# Setup SimpleBlobDetector parameters.
params = cv2.SimpleBlobDetector_Params()
params.blobColor= 255
params.filterByColor = True
# Create a detector with the parameters
ver = (cv2.__version__).split('.')
if int(ver[0]) < 3 :
detector = cv2.SimpleBlobDetector(params)
else :
detector = cv2.SimpleBlobDetector_create(params)
# Detect blobs.
keypoints = detector.detect(opening)
# Draw detected blobs as green circles.
# cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS ensures
# the size of the circle corresponds to the size of blob
print str(keypoints)
im_with_keypoints = cv2.drawKeypoints(opening, keypoints, np.array([]), (0,255,0), cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
# Show blobs
##cv2.imshow("Keypoints", im_with_keypoints)
cv2.imwrite('Keypoints.jpg',im_with_keypoints)
cv2.waitKey(0)
EDIT:
By adding a bigger value of area maximum value, i am able to identify a big blob but my end goal is to identify the big white rectangle exist or not. And the white blob detection i did returns not only the rectangle but also the surrounding areas as well. [This part solved]
EDIT 2:
Based on the answer from #PSchn, i update my code to apply the logic, first set the color filter to only get the white pixels and then remove the noise point using opening. It works for the sample data and i can successfully get the keypoint after blob detection.
If you just want to detect the white rectangle you can try to set a higher threshold, e.g. 253, erase small object with an opening and take the biggest blob. I first smoothed your image, then thresholding it:
and the opening:
now you just have to use findContours and take the boundingRect. If your rectangle is always that white it should work. If you get lower then 251 with your threshold the other small blobs will appear and your region merges with them, like here:
Then you could still do an opening several times and you get this:
But i dont think that it is the fastest idea ;)
You could try setting params.maxArea to something obnoxiously large (somewhere in the tens of thousands): the default may be something lower than the area of the rectangle you're trying to detect. Also, I don't know how true this is or not, but I've heard that detection by color is bugged with a logic error, so it may be worth a try disabling it just in case that is causing problems (this has probably been fixed in later versions, but it could still be worth a try)

Deciding parameters in HoughCircles method of OpenCV

I am trying to detect circles in an image, and am using OpenCV Python for the same. I am facing problems when I use the HoughCircles method. I am using the following custom image , but my code is unable to detect both circles.
I tried the following implementation
circles = cv2.HoughCircles(thresh1,cv2.cv.CV_HOUGH_GRADIENT,2,1,param1=100,param2=100,minRadius=0,maxRadius=1000)
and this is only properly detecting the bigger circle in the image. I'm pretty sure if I tinker around with the parameters , I might hit upon a combination that works, but is there any way I can calculate, or figure out the parameters, given an image?
EDIT
Here is the entire code that I have written:
import cv2
import numpy as np
def show(s , i):
cv2.imshow(s , i)
cv2.waitKey(0)
cv2.destroyAllWindows()
img = cv2.imread('ball2.jpg')
show("img" , img)
img = cv2.medianBlur(img,5)
cimg = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ret,thresh1 = cv2.threshold(cimg,10,255,cv2.THRESH_BINARY)
show('thresh' , thresh1)
circles = cv2.HoughCircles(thresh1,cv2.cv.CV_HOUGH_GRADIENT,2,1,param1=100,param2=100,minRadius=0,maxRadius=1000)
print circles
circles = np.uint16(np.around(circles))
for i in circles[0,:]:
# draw the outer circle
cv2.circle(thresh1,(i[0],i[1]),i[2],(100,150,120),2)
# draw the center of the circle
cv2.circle(thresh1,(i[0],i[1]),2,(0,0,0),3)
cv2.imshow('detected circles',thresh1)
cv2.waitKey(0)
cv2.destroyAllWindows()
Have you seen http://www.pyimagesearch.com/2014/07/21/detecting-circles-images-using-opencv-hough-circles/?
Author there suggests to tinker with minDist, as the most important parameter, but you have that set to 1, so rather we should expect false positive than not found circles.
I suggest also to increase param1 to 200 to set upper threshold for the internal Canny edge detector for increased detection.
Also I found some people reported weird anomaly, where increasing maxradius resulted in getting fewer circles. Sometimes it's good idea to leave optional parameters as default (value 0).
From my experience with openCV it often ends up with tinkering parameters to get best results.

Python/OpenCV - Colored Droplets Recognition and Tracking

I'm a semi-noob in Video Analysis.
I have a Petri dish with some colored droplets inside and I must detect them, and keep trace of their position,area and color.
I want first to detect my Petri dish (maybe using HoughCircles) and define a ROI on which work later.
The problem is that mi dish detection is very "noisy": the program detects many circles (and I only need the one corresponding to the dish) and it never detects the right one.
Here is my code:
import cv2
import numpy as np
def main():
cap=cv2.VideoCapture("dropletsS.wmv")
cv2.namedWindow("prova")
while(1):
ret, RGBframe = cap.read()
grayFrame = cv2.cvtColor(RGBframe,cv2.COLOR_BGR2GRAY)
grayFrame=cv2.medianBlur(grayFrame,7)
circles=cv2.HoughCircles(grayFrame,cv2.HOUGH_GRADIENT ,50,50)
for c in circles[0,:]:
cv2.circle(RGBframe,(c[0],c[1]),c[2],(0,255,0),2)
cv2.imshow("prova", RGBframe)
cv2.imshow("grigio", grayFrame)
cv2.waitKey(10)
if __name__ == "__main__":
main()
And here is the result.
Do someone have some suggestions? Suggestions on the way I can later identify and track droplets are welcome too.
Thanks in advance!
Its kind of hard to come up with a solution without having much of an idea on how the dish actually looks like, but I'll try helping you anyways.
If the problem is what I think it is, then you can probably open and dilate your image to join all the discontinuous blobs.
Do the following before you apply Hough Transform:
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5,5)) #declare outside while
grayFrame = cv2.morphologyEx(grayFrame, cv2.MORPH_OPEN, kernel)
grayFrame = cv2.dilate(grayFrame, kernel, iterations = 2)
Let me know if the output is output image that you desire. Also play around with the parameters to get the required result. You can change the dimensions of the MORPH_ELLIPSE and also the number of iterations. Increasing any of them would increase the degree of dilation, thus more of the blobs would join up and vice versa.

Categories