Eye Pupil Tracking using Hough Circle Transform - python-2.7

I have a project of Eye Controlled Wheel Chair where I need to detect the pupil of the Eye and according to its motion the Wheel Chair moves. As a test for the code I am writing I performed the script on a static image. The image is exactly where the camera will be put. The camera will be an IR one.
Note: I am using compiled OpenCV 3.1.0-dev and Python2.7 on Windows Platfrom
The detected circle I wanted using Houghcircle transform:
After that I am working on a code to detect the same thing only by using an IR camera.
The results from the static image code is very reliable to me, but the problem is the code with the IR camera.
The code I have wrote so far is:
import cv2
import numpy as np
cap = cv2.VideoCapture(0)
while True:
## Read Image
ret, image = cap.read()
## Convert to 1 channel only grayscale image
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
## CLAHE Equalization
cl1 = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))
clahe = cl1.apply(gray)
## medianBlur the image to remove noise
blur = cv2.medianBlur(clahe, 7)
## Detect Circles
circles = cv2.HoughCircles(blur ,cv2.HOUGH_GRADIENT,1,20,
param1=50,param2=30,minRadius=7,maxRadius=21)
if circles != None:
circles = np.round(circles[0,:]).astype("int")
for circle in circles[0,:]:
# draw the outer circle
cv2.circle(image,(circle[0],circle[1]),circle[2],(0,255,0),2)
# draw the center of the circle
cv2.circle(image,(circle[0],circle[1]),2,(0,0,255),3)
if cv2.waitKey(1) in [27, ord('q'), 32]:
break
cap.release()
cv2.destroyAllWindows()
I always get this error:
**if circles != None:
FutureWarning: comparison to `None` will result in an elementwise object comparison in the future.
Traceback (most recent call last):
cv2.circle(image,(circle[0],circle[1]),circle[2],(0,255,0),2)
IndexError: invalid index to scalar variable.**
For any questions about the code for the static image, the code is:
import cv2
import numpy as np
## Read Image
image = cv2.imread('eye.tif')
imageBackup = image.copy()
## Convert to 1 channel only grayscale image
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
## CLAHE Equalization
cl1 = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))
clahe = cl1.apply(gray)
## medianBlur the image to remove noise
blur = cv2.medianBlur(clahe, 7)
## Detect Circles
circles = cv2.HoughCircles(blur ,cv2.HOUGH_GRADIENT,1,20,
param1=50,param2=30,minRadius=7,maxRadius=21)
for circle in circles[0,:]:
# draw the outer circle
cv2.circle(image,(circle[0],circle[1]),circle[2],(0,255,0),2)
# draw the center of the circle
cv2.circle(image,(circle[0],circle[1]),2,(0,0,255),3)
cv2.imshow('Final', image)
cv2.imshow('imageBackup', imageBackup)
cv2.waitKey(0)
cv2.destroyAllWindows()

So i tried it out my self and i had the same error. So i modified the code like i already proposed. Here is the snipped:
if circles != None:
for circle in circles[0,:]:
# draw the outer circle
cv2.circle(image,(circle[0],circle[1]),circle[2],(0,255,0),2)
# draw the center of the circle
cv2.circle(image,(circle[0],circle[1]),2,(0,0,255),3)
In addition you can try to use cv2.Canny for better results. Over and out :)

Related

How can i use Viola Jones Algorithm to detect the Face as a region of interest and crop it till the rectangle box?

I want to detect the face in the video frame and remove the other elements such as background etc. and just want to focus on the facial region, for this i need to use viola jones algorithm, czn anyone give me a hint or suitable answer for this.
import cv2
import sys
imagep='6.jpg'#sys.argv[1]
face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')
i=cv2.imread(imagep)
gray=cv2.imread(imagep,cv2.COLOR_BGR2GRAY)
f=face_cascade.detectMultiScale(gray,scaleFactor=1.1,minNeighbors=5,minSize=(30,30),flags=cv2.CASCADE_SCALE_IMAGE)
print("Found {0} faces!".format(len(f)))
for(x,y,w,h) in f:
cv2.rectangle(i,(x,y),(x+w,y+h),(0,255,0),2)
cv2.imshow("Faces found",i)
cv2.waitKey(0)
Once you have the upper left and and bottom right coordinates of the rectangle in which the face is contained, You can just crop the original image on the basis of those coordinates. Let's suppose initial image is stored in the frame variable, follow the code
face = face_recognition.detectMultiScale(frame, scaleFactor = 1.8, minNeighbors = 5) #detects coordinates of face
resultant_image = frame[face[0][1] : (face[0][1] + face[0][3]),face[0][0] : (face[0][0] + face[0][2]), :] # gives you cropped image

detect filled rectangles in image

How to detect filled rectangles in image?
I need to get the bounding box for the 4 white (filled with white) rectangles in the right side of the image, but not the big rectangle in the middle with a white outline
You can isolate each contour by drawing the contour on a mask. Then you can use that mask on the image to calculate the average color. A high average indicates that the contour contains mostly white, so it is likely a contour you want.
Result:
Code:
import numpy as np
import cv2
#load the image
img = cv2.imread("form.png")
# create grayscale
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
#Find contours (external only):
im, contours, hierarchy = cv2.findContours(gray, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
#draw contours on original image
for cnt in contours:
# disregard small contours cause by logo and noise
if cv2.contourArea(cnt) > 10000:
#isolate contour and calculate average pixel value
mask = np.zeros(gray.shape[:2],np.uint8)
cv2.drawContours(mask,[cnt],0,255,-1)
mean_val = cv2.mean(gray,mask = mask)
# a high value indicates the contour contains mostly white, so draw the contour (I used the boundingRect)
if mean_val[0] > 200:
x,y,w,h = cv2.boundingRect(cnt)
cv2.rectangle(img, (x,y),(x+w,y+h), (0,0,255), thickness=4)
# show/save image
cv2.imshow("Image", mask)
cv2.imwrite("result.jpg", img)
cv2.waitKey(0)
cv2.destroyAllWindows()
Note: you can also load the image as grayscale and skip creating one, but I used it here so I could draw more obvious red boxes.
Also be aware the code given might not generalize well, but it shows the concept.

segmentation of overlapping cells

The following python script should split overlapping cells apart which does work quite good. The problem is now that it also splits some of the cells apart which don't overlap with other cells. To make things clear to you i'll add my input image and the output image.
The input:input image
The output:
output image
Output image where I marked two "bad" segmented cells:Output image with marked errors
Thresholded image: Thresholded image
Does someone have an idea how to avoid this problem or is the whole approach not good enough to process these kind of images?
I am using the following piece of code to segment the cells:
from skimage.feature import peak_local_max
from skimage.morphology import watershed
from scipy import ndimage
import numpy as np
import cv2
# load the image and perform pyramid mean shift filtering
# to aid the thresholding step
image = cv2.imread('C:/Users/Root/Desktop/image13.jpg')
shifted = cv2.pyrMeanShiftFiltering(image, 41, 51)
# convert the mean shift image to grayscale, then apply
# Otsu's thresholding
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255,
cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
im = gray.copy()
D = ndimage.distance_transform_edt(thresh)
localMax = peak_local_max(D, indices=False, min_distance=3,
labels=thresh)
# perform a connected component analysis on the local peaks,
# using 8-connectivity, then apply the Watershed algorithm
markers = ndimage.label(localMax, structure=np.ones((3, 3)))[0]
labels = watershed(-D, markers, mask=thresh)
print("[INFO] {} unique segments found".format(len(np.unique(labels)) - 1))
conts=[]
for label in np.unique(labels):
# if the label is zero, we are examining the 'background'
# so simply ignore it
if label == 0:
continue
# otherwise, allocate memory for the label region and draw
# it on the mask
mask = np.zeros(gray.shape, dtype="uint8")
mask[labels == label] = 255
# detect contours in the mask and grab the largest one
cnts = cv2.findContours(mask.copy(), cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE)[-2]
c = max(cnts, key=cv2.contourArea)
rect = cv2.minAreaRect(c)
box = cv2.boxPoints(rect)
box = np.int0(box)
if cv2.contourArea(c) > 150:
#cv2.drawContours(image,c,-1,(0,255,0))
cv2.drawContours(image,[box],-1,(0,255,0))
cv2.imshow("output", image)
cv2.waitKey()

Change origin of image coordinate system to bottom left instead of default top left

Is there a simple way of changing the origin of image co-ordinate system of OpenCV to bottom left? Using numpy for example? I am using OpenCv 2.4.12 and Python 2.7.
Related: Numpy flipped coordinate system, but this talks about just display. I want something which I can use consistently in my algorithm.
Update:
def imread(*args, **kwargs):
img = plt.imread(*args, **kwargs)
img = np.flipud(img)
return img
#read reference image using cv2.imread
imref=cv2.imread('D:\\users\\gayathri\\all\\new\\CoilA\\Resized_Results\\coilA_1.png',-1)
cv2.circle(imref, (0,0),30,(0,0,255),2,8,0)
cv2.imshow('imref',imref)
#read the same image using imread function
im=imread('D:\\users\\gayathri\\all\\new\\CoilA\\Resized_Results\\coilA_1.png',-1)
img= im.copy()
cv2.circle(img, (0,0),30,(0,0,255),2,8,0)
cv2.imshow('img',img)
Image read using cv2.imread:
Image flipped using imread function:
As seen the circle is drawn at the origin on upper left corner in both original and flipped image. But the image looks flipped which I do not desire.
Reverse the height (or column) pixels will get the result below.
import numpy as np
import cv2
import matplotlib.pyplot as plt
%matplotlib inline
img = cv2.imread('./imagesStackoverflow/flip_body.png') # read as color image
flip = img[::-1,:,:] # revise height in (height, width, channel)
plt.imshow(img[:,:,::-1]), plt.title('original'), plt.show()
plt.imshow(flip[:,:,::-1]), plt.title('flip vertical'), plt.show()
plt.imshow(img[:,:,::-1]), plt.title('original with inverted y-axis'), plt.gca().invert_yaxis(), plt.show()
plt.imshow(flip[:,:,::-1]), plt.title('flip vertical with inverted y-axis'), plt.gca().invert_yaxis(), plt.show()
Output images:
Above included the one you intended to do?

OpenCV 2.4.9 for Python, cannot find chessboard (camera calibration tutorial)

I am trying to calibrate camera using OpenCV tools according to the following this guide.
The problem is that function findChessboardCorners cannot find any chessboard on images I tried. I used a lot of them - even just plain chessboard pattern. In any case, nothing was detected.
Here is the code (almost the same as from link above):
import numpy as np
import cv2
import glob
# termination criteria
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)
# prepare object points, like (0,0,0), (1,0,0), (2,0,0) ....,(6,5,0)
objp = np.zeros((6*7,3), np.float32)
objp[:,:2] = np.mgrid[0:7,0:6].T.reshape(-1,2)
# Arrays to store object points and image points from all the images.
objpoints = [] # 3d point in real world space
imgpoints = [] # 2d points in image plane.
images = glob.glob('*.png')
for fname in images:
img = cv2.imread(fname)
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
# Find the chess board corners
ret, corners = cv2.findChessboardCorners(gray, (7,6),None)
# If found, add object points, image points (after refining them)
if ret == True:
objpoints.append(objp)
corners2 = cv2.cornerSubPix(gray,corners,(11,11),(-1,-1),criteria)
imgpoints.append(corners2)
# Draw and display the corners
img = cv2.drawChessboardCorners(img, (7,6), corners2,ret)
cv2.imshow('img',img)
cv2.waitKey(500)
cv2.destroyAllWindows()
The only change I made is that i switched from .jpg files to .png files - for some reason, function imread cannot read jpg images (that's another strange problem for other topic).
Thank you in advance for advices!
Image ref:
Just for other Python newbies that may go down this road. Working code:
import numpy as np
import cv2
import glob
# termination criteria
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)
# Arrays to store object points and image points from all the images.
imgpoints = [] # 2d points in image plane.
images = glob.glob('*.png')
for fname in images:
img = cv2.imread(fname)
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ret = False
# Find the chess board corners
ret, corners = cv2.findChessboardCorners(gray, (7,7))
# If found, add object points, image points (after refining them)
if ret == True:
cv2.cornerSubPix(gray, corners, (11,11), (-1,-1), criteria)
imgpoints.append(corners)
# Draw and display the corners
cv2.drawChessboardCorners(img, (7,7), corners, ret)
cv2.imshow('img',img)
cv2.waitKey(0)
cv2.destroyAllWindows()
Two main points:
You have to carefully count dimension of you pattern. (7,7) is for usual chessboard.
Line img = cv2.drawChessboardCorners(img, (7,6), corners2,ret) doesn't work, you have to change it to cv2.drawChessboardCorners(img, (7,6), corners2,ret) (function doesn't return image).
Thanks to AldurDisciple!