I am trying to identify numbers in images. I am using the cv2.findContours function to "separate" the digits in the photo. But even after several modifications to the image the function recognises arbitrary contours even in the absolute top left corner of the image even though the final modified image has an absolutely black background with only the digits being white. Why is it so? Complete source code along with photo and everything else :
https://github.com/tanmay-edgelord/HandwrittenDigitRecognition
Source code :
https://github.com/tanmay-edgelord/HandwrittenDigitRecognition/blob/master/performRecognition.ipynb
In this code I am using the rects = [cv2.boundingRect(ctr) for ctr in ctrs] line to identify the contours returned by the function. Upon printing it out I found out that many of the bounding rectangles are in (0,0,0,0). If any further details/clarification is required please comment.
Related
My project is REM sleep detector, and the provided pictures show the contour of my eyelid. As my eye looks in directions, this contour moves in a distinct way. For lack of a better solution, my first attempt is to draw a grid of rois on my video stream, with that in place I want to use the countnonzero function or use blob detection on the rois. Depending on which rois in the grid change values, movement and direction is detected. (I am sure there is better way)
Problem: I can not specify one or several rois of my choice, the function always work only on the entire image. How do I retrieve values from each roi specifically? Rois are set up by means of multiple rectangle functions. Code is in python. Any help greatly appreciated.
Contour of eyelid:
I'm trying to extract some contents from a cropped image. I tried pytesseract and opencv template matching but the results are very poor. OpenCV template matching sometimes fails due to poor quality of the icons and tesseract gives me a line of text with false characters.
I'm trying to grab the values like this:
0:26 83 1 1
Any thoughts or techniques?
A technique you could use would be to blur your image. From what it looks like, the image is kind of low res and blurry already, so you wouldn't need to blur the image super hard. Whenever I need to use a blur function in Opencv, I normally choose the gaussian blur, as its technique of blurring each pixel as well as each surrounding pixel is great. Once the image is blurred, I would threshold, or adaptive threshold the image. Once you have gotten this far, the image that should be shown should be mostly hard lines with little bits of short lines mixed between. Afterwards, dilate the threshold image just enough to have the bits where there are a lot of hard edges connect. Once a dilate has been performed, find the contours of that image, and sort based on their height with the image. Since I assume the position of those numbers wont change, you will only have to sort your contours based on the height of the image. Afterwards, once you have sorted your contours, just create bounding boxes over them, and read the text from there.
However, if you want to do this the quick and dirty way, you can always just manually create your own ROI's around each area you want to read and do it that way.
First Method
Gaussian blur the image
Threshold the image
Dilate the image
Find Contours
Sort Contours based on height
Create bounding boxes around relevent contours
Second Method
Manually create ROI's around the area you want to read text from
The role of this program is to draw Houghlines on an external window, when lines are detected in a game. However, when I implemented the ROI to avoid having useless lines detected, the border of the ROI is still detected as a line (obviously it is)
As shown in the image below, you may notice how the arrow show the detected line from the ROI.
How can I make it that it ignores the lines around the border?
I tried to overlap the ROI with other lines but openCV still detects the borders as lines.
I am using Python.
Thanks!
Solved it, was an amateur mistake! If anyone meets this problem, you will have to fix it by putting the region of interest code after converting the image to gray and then to edge detection; hence, Convert image to gray -> Convert image to Canny/Sobel (edge detection) -> Set image to ROI
What I'm trying to do is find big light polluted areas in a photo of nighttime Earth. I converted the source photo to grayscale and then to binary photo with a threshold. cv2.findcontours works properly but when I try to get rid of small contours it only deletes a part of them.
Source image
import cv2
image_orig=cv2.imread('C:\Users\pc\Desktop\middleeast.jpg')
image_gray=cv2.cvtColor(image_orig,cv2.COLOR_BGR2GRAY)
_, image_threshold=cv2.threshold(image_gray,60,255,cv2.THRESH_BINARY)
_,contours,_=cv2.findContours(image_threshold,cv2.RETR_LIST,cv2.CHAIN_APPROX_NONE)
image_contours=image_orig.copy()
cv2.drawContours(image_contours,contours,-1,(255,255,0),1)
cv2.imshow('image_contours',image_contours)
cv2.imwrite('C:\Users\pc\Desktop\middleEastAllContours.jpg', image_contours)
for counter,contour in enumerate(contours):
if cv2.contourArea(contour)<250.0:
contours.pop(counter)
image_big_contours=image_orig.copy()
cv2.drawContours(image_big_contours,contours,-1,(255,255,0),1)
cv2.imshow('big contours',image_big_contours)
cv2.waitKey(0)
As you can see there still are plenty of small light polluted areas contoured. How can I get rid of them?
All contours comparison
Big contours comparison
Source image all contours Source image big contours
I think that the problem is in the pop of the for: when you pop a contour, you are skipping the next one.
For example, if you pop contour number 10, then the next countour will become number 10, but you will skip it because in the next iteration you will look at contour 11.
I am not a python expert (I don't really know how the two variables are used in the for) but you could try to do a counter=counter-1 after the pop. Another option is iterate the list backwards (start in the last element and finish at the first)
I am attempting to write a program to handle the finding the intersections of the lines outlining a rectangular object, (eg. Computer screen). I attempted to use hough lines originally, however, due to variable lighting conditions as well as content appearing on the screen, the lines that are drawn are not always the outline of the screen. Additionally, there may be a large amount of other random objects in the frame.
My next approach was to use contours which always seem to outline both the screen as well as being able to handle the variable content encapsulated within it. How do I go about using the contours to approximate a line?
I used
print len(contours)
and received a contour fairly long contour length > 200 consistently.
Feel free to comment asking for clarity.
EDIT
The green "lines" are the contours found by findContours. I am primarily interested in the contour surrounding the screen content. How can I use those contours to find a line approximating those contours and then find the point of intersection of the two lines? This is from a webcam stream so conditions, angle, and distance may not stay constant.
A first step might be to use the size of the contours to filter out those you are not interested in since the smaller contours usually correspond to stuff on the screen.
Also, the findContour method can be used to return the contours in a hierarchy of nested contours. This will tell you which contour is contained within another and allow you to get the outer-most, second outer-most one etc. If you are trying to get the screen, then it would have to be a large contour that is possibly the second largest and nested just below the contour for the monitor.
After obtaining the potential contours, which are just list of points, you can do a robust fitting for a single rectangle using just these points either by RANSAC (with a model for rectangles, not homography), or hough transform modified for this case.