Reputation: 499
I have the image of a wheel and I want to detect the ellipse that maps to this wheel (or the inner circle of the wheel) with OpenCV (for pose estimation of the vehicle/wheel).
[![enter image description here][1]][1]
Does anyone know how to do this?
[![enter image description here][2]][2]
The resulting image should look like this (or somewhat like this - I need to retrieve a few points that go through the ellispe). Please note, the result should be an ellipse, not a circle, because the wheel can be in perspective/in distortion, if looked at from the side.
So far I experimented with Contour (and identifying the largest contour area), canny, and color thresholding, I am able to identify the inner ellipse of the wheel on most of my test images (success!). This "inner ellipse" is part of the largest contour, however it contains other points as well that I don't need.
See image: [![enter image description here][3]][3]
The final question is, how to derive a few points of this inner circle/ellipse (and get rid of the other garbage) such that I can calculate the ellipse parameters?
Any help would be appreciated.
Many thanks!
EDIT:
Here is my code so far:
import sys
import numpy as np
import skimage.io
import skimage.filters
import matplotlib.pyplot as plt
import cv2
from skimage import data, color, img_as_ubyte
from skimage.feature import canny
from skimage.transform import hough_ellipse
from skimage.draw import ellipse_perimeter
# get filename and sigma value from command line
filename0 = 'back_wheel.png'
filename1 = "backwheel1.png"
filename2 = "backwheel2.png"
filename3 = "backwheel3.png"
filename4 = "frontwheel1.png"
filename5 = "frontwheel2.png"
def getWheel0(filename):
image_rgb_orig = cv2.imread(filename)
image_rgb = image_rgb_orig.copy()
print('Original Dimensions : ',image_rgb.shape)
width = 350
height = (int)(width * image_rgb.shape[0]/image_rgb.shape[1])
dim = (width, height)
image_rgb = cv2.resize(image_rgb, dim, interpolation=cv2.INTER_AREA)
image_gray = cv2.cvtColor(image_rgb, cv2.COLOR_BGR2GRAY)
equ = cv2.equalizeHist(image_gray)
#edges = cv2.Canny(image_gray, 150, 200)
norm_image = cv2.normalize(equ, None, alpha=0, beta=1, norm_type=cv2.NORM_MINMAX)
#--- First obtain the threshold using the greyscale image ---
ret,th = cv2.threshold(norm_image, 50, 100, cv2.THRESH_TOZERO_INV)
#--- Find all the contours in the binary image ---
contours,hierarchy = cv2.findContours(th,2,1)
#contours, hierarchy = cv2.findContours(th, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_TC89_L1)
cnt = contours
big_contour = []
max = 0
for i in cnt:
area = cv2.contourArea(i) #--- find the contour having biggest area ---
if(area > max):
max = area
big_contour = i
result = cv2.drawContours(image_rgb, big_contour, -1, (0,255,0), 3)
fig2, (ax1, ax2, ax3) = plt.subplots(ncols=3, nrows=1, figsize=(8, 4), sharex=True,
sharey=True)
ax1.set_title('Original picture')
ax1.imshow(image_rgb_orig)
ax2.set_title('Threshhold')
ax2.imshow(th)
ax3.set_title('Contour')
ax3.imshow(result)
plt.show()
getWheel0(filename0)
getWheel0(filename1)
getWheel0(filename2)
getWheel0(filename3)
getWheel0(filename4)
getWheel0(filename5)
running it with "python tire.py"
Upvotes: 1
Views: 1267
Reputation: 499
Thank you all for your posts. These were very helpful to come close to an answer. I finally end up doing the following:
grayscale normalize findContours
Then on the contours, I do cornerHarris, which returns a Mat of the size of the image with a corner value for each pixel of the contours.
I normalize the values of the cornerHarries Mat to values between 0 and 255. 0 are straight lines (no corners), and I then set every value below 2 (straight lines) and any value above 20 to 255, such that only "soft curves" remain in the Mat.
After this step I loop through the Mat and remove all values that =255 or that are in close distance to the points that are 255.
The result is (at least for this one test image) that only a part of the ellipse points remain, and these are enough for findEllipse to return the correct ellipse.
Upvotes: 0
Reputation: 901
The problem of locating circle on an image is well-known and is already solved.
Use Hough circle transform. It's a basic functionality of OpenCV lib to: docs.
Generalized Hough transform may be used to detect ellipses. But you will need to code it yourself since, some reasonable ideas provided in answers to this question. You need accumulator with more dimensions (5) that in case of line (2) or circle (3) detection but it shouldn't be a problem.
It also look like canny gives good edges on your image. You can try following:
Both of this solutions might not work good for ovals and ellips-like contours with asymmetrical axes.
Upvotes: 1