Je si s tím potřeba ještě pohrát, zdaleka to není univerzální řešení. Testoval jsem to jen na prvním obrázku a při stažení toho posuvníku na nízký treshold to dává snad i celkem přijatelné výsledky (jestli jsou teda ty buňky tři). Pro jiné obrázky to pravděpodobně už tak dobře fungovat nebude, kritické bude mít správné parametry ve funkci pro odstraňování zelené barvy. Tam by možná stálo za to vyzkoušet chytit se histogramu:
http://docs.opencv.org/doc/tutorials/imgproc/histograms/histogram_calculation/histogram_calculation.html#histogram-calculation. Obecně platí, že pro testování něčeho takového to bude chtít mnohem víc obrázků než jen dva.
Teď jsem na to ještě nesebral síly ale dobré by bylo testovat kolize obdélníků a případně je slučovat do větších. Jakési nehotové cosi tam je přítomno

.
Minimální velikost obdélníku, který bude vykreslen je pevně zafixovaná, to je špatně. Řekl bych, že by bylo vhodné vycházet z úrovně zazoomování foťáku a fyzické velikosti buňek, když se něco ví jistě, není potřeba se k tomu zkoušet nějak doadaptovávat.
No, zlomte vaz a nenamnožte si tam zelené mužíky

//============================================================================
// Name : ocv_bunky.cpp
// Author : Buněčňák
// Version :
// Copyright : moje
// Description : Hello World in C++, Ansi-style
//============================================================================
//zalozeno na http://docs.opencv.org/doc/tutorials/imgproc/shapedescriptors/bounding_rects_circles/bounding_rects_circles.html#bounding-rects-circles
#include <iostream>
#include <stdlib.h>
#include <math.h>
#include <cv.h>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
using namespace std;
using namespace cv;
Mat imgSeda;
int thresh = 100;
int max_thresh = 255;
RNG rng(12345);
/// Function header
void thresh_callback(int, void* );
inline bool zdaKolize(Rect A,Rect B)
{
if((max(A.x,B.x)<min((A.x+A.width),(B.x+B.width)))&&(max(A.y,B.y)<min(A.y+A.height,B.y+B.height)))
return true;else return false;
}
inline Rect sloucitRect(Rect A,Rect B)
{
Rect vratit;
vratit.x=min(A.x,B.x);
vratit.y=min(A.y,B.y);
vratit.width=max(A.x+A.width,B.x+B.width);
vratit.height=max(A.y+A.height,B.y+B.height);
}
inline void zbavitZelene(Mat & img,int posileniModre=10,int posileniCervene=10)
{
for(int i=0;i<img.rows;i++)
for(int j=0;j<img.cols;j++)
{
Vec3b pixel=img.at<Vec3b>(i,j);
pixel[0]*=posileniModre;
pixel[1]=0;//zelenou odstranit
pixel[2]*=posileniCervene;
if(pixel[2]<100||pixel[0]<100)
{
pixel[2]=0;
pixel[0]=0;
}
img.at<Vec3b>(i,j)=pixel;
}
}
int main ( int argc, char **argv )
{
Mat img=imread("bunky.jpg",1);
zbavitZelene(img);
cvtColor( img, imgSeda, CV_BGR2GRAY );
blur( imgSeda, imgSeda, Size(3,3) );
imshow( "Source", img );
createTrackbar( " Threshold:", "Source", &thresh, max_thresh, thresh_callback );
thresh_callback( 0, 0 );
cvWaitKey();
return 0;
}
/** @function thresh_callback */
void thresh_callback(int, void* )
{
Mat threshold_output;
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
/// Detect edges using Threshold
threshold( imgSeda, threshold_output, thresh, 255, THRESH_BINARY );
/// Find contours
findContours( threshold_output, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );
/// Approximate contours to polygons + get bounding rects and circles
vector<vector<Point> > contours_poly( contours.size() );
vector<Rect> boundRect( contours.size() );
vector<Point2f>center( contours.size() );
vector<float>radius( contours.size() );
for( int i = 0; i < contours.size(); i++ )
{ approxPolyDP( Mat(contours[i]), contours_poly[i], 3, true );
boundRect[i] = boundingRect( Mat(contours_poly[i]) );
minEnclosingCircle( (Mat)contours_poly[i], center[i], radius[i] );
}
/// Draw polygonal contour + bonding rects + circles
Mat drawing = Mat::zeros( threshold_output.size(), CV_8UC3 );
//test pruniku
/*for(int i=0;i<contours.size();i++)
for(int j=i;j<contours.size();j++)
if(zdaKolize(boundRect[i],boundRect[j]))
{
printf("slouceno");
boundRect[i]=sloucitRect(boundRect[i],boundRect[j]);
//boundRect[j].width=0;
boundRect.erase(boundRect.begin()+j);
}*/
for( int i = 0; i< contours.size(); i++ )
{
//Scalar color = Scalar( rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255) );
//drawContours( drawing, contours_poly, i, color, 1, 8, vector<Vec4i>(), 0, Point() );
if(boundRect[i].width * boundRect[i].height>100)
rectangle( drawing, boundRect[i].tl(), boundRect[i].br(), Scalar(255,0,0), 2, 8, 0 );
//circle( drawing, center[i], (int)radius[i], color, 2, 8, 0 );
}
/// Show in a window
namedWindow( "Contours", CV_WINDOW_AUTOSIZE );
imshow( "Contours", drawing );
}