Sorry I don't know OpenCV, and this is more a pre-processing step than a complete answer:
First, you don't want an edge detector. An edge detector converts transitions (like this dark-to-light):
into ridges (bright lines on dark) like this:
It performs a differentiation, in other words.
But in your images, there is a light shining down from one direction, which shows us the relief of the 3D surface. We perceive this as lines and edges, because we're used to seeing things in 3D, but they aren't really, which is why edge detectors aren't working, and template matching won't work easily with rotated images (a perfect match at 0 degrees rotation would actually cancel out completely at 180 degrees, because light and dark would line up with each other).
If the height of one of these mazy lines looks like this from the side:
then the brightness function when illuminated from one side will look like this:
This is what you see in your images. The facing surface becomes brighter and the trailing surface becomes darker. So you don't want to differentiate. You need to integrate the image along the direction of illumination, and it will give you the original height map of the surface (approximately). Then it will be easier to match things, whether through Hough transform or template matching or whatever.
I'm not sure how to automate finding the direction of illumination. If it's the same for all your images, great. Otherwise you'd have to find the biggest contrast line and assume the light is perpendicular to it or something. For my example, I rotated the image manually to what I thought was the right direction, with light coming from the left:
You also need to remove all the low-frequency changes in the image, though, to highlight only the quickly-changing line-like features. To avoid ringing artifacts, I used 2D Gaussian blur and then subtracted that from the original:
The integration (cumulative sum) can runaway easily, which produces horizontal streaks. I removed these with another Gaussian high-pass, but only in the horizontal direction this time:
Now the stomata are white ellipses all the way around, instead of white in some places and black in others.
from pylab import *
from scipy.ndimage import gaussian_filter, gaussian_filter1d
filename = 'rotated_sample.jpg'
I = Image.open(filename).convert('L')
I = asarray(I)
# Remove DC offset
I = I - average(I)
# Remove slowly-varying features
sigma_2d = 2
I = I - gaussian_filter(I, sigma_2d)
title('2D filtered with %s' % sigma_2d)
summed = cumsum(I, 1)
# Remove slowly-changing streaks in horizontal direction
sigma_1d = 5
output = summed - gaussian_filter1d(summed, sigma_1d, axis=1)
title('1D filtered with %s' % sigma_1d)
The Hough transform can be used to detect ridge ellipses like this, made of "edge pixels", though it's really expensive in computation and memory, and they are not perfect ellipses so it would have to be a bit of a "sloppy" detector. I've never done it, but there are a lot of Google results for "hough ellipse detection". I'd say if you detect one ellipse inside the other, within a certain size search space, it should be counted as a stoma.