Je suis nouveau à OpenCV et j'essaie de compter le nombre d'objets dans une image. Je l'ai fait avant d'utiliser MATLAB Image Processing Toolbox et adapté la même approche dans OpenCV (Android) aussi.compter les objets et une meilleure façon de remplir les trous
La première étape consistait à convertir une image en échelle de gris. Ensuite, pour le seuil et ensuite en comptant le nombre de blobs. Dans Matlab il y a une commande - "bwlabel", qui donne le nombre de blobs. Je ne pouvais pas trouver une telle chose dans OpenCV (encore une fois, je suis un Noob dans OpenCV ainsi que Android).
Voici mon code,
//JPG to Bitmap to MAT
Bitmap i = BitmapFactory.decodeFile(imgPath + "mms.jpg");
Bitmap bmpImg = i.copy(Bitmap.Config.ARGB_8888, false);
Mat srcMat = new Mat (bmpImg.getHeight(), bmpImg.getWidth(), CvType.CV_8UC3);
Utils.bitmapToMat(bmpImg, srcMat);
//convert to gray scale and save image
Mat gray = new Mat(srcMat.size(), CvType.CV_8UC1);
Imgproc.cvtColor(srcMat, gray, Imgproc.COLOR_RGB2GRAY,4);
//write bitmap
Boolean bool = Highgui.imwrite(imgPath + "gray.jpg", gray);
//thresholding
Mat threshed = new Mat(bmpImg.getWidth(),bmpImg.getHeight(), CvType.CV_8UC1);
Imgproc.adaptiveThreshold(gray, threshed, 255, Imgproc.ADAPTIVE_THRESH_MEAN_C, Imgproc.THRESH_BINARY, 75, 5);//15, 8 were original tests. Casey was 75,10
Core.bitwise_not(threshed, threshed);
Utils.matToBitmap(threshed, bmpImg);
//write bitmap
bool = Highgui.imwrite(imgPath + "threshed.jpg", threshed);
Toast.makeText(this, "Thresholded image saved!", Toast.LENGTH_SHORT).show();
Dans la prochaine ste p, j'ai essayé de remplir les trous et les lettres en utilisant la dilatation suivie d'une érosion mais les gouttes se sont attachées les unes aux autres ce qui donnera finalement un mauvais compte. Il y a un compromis entre remplir les trous et obtenir les blobs attachés les uns aux autres sur l'accord des paramètres pour la dilatation et l'érosion.
Voici le code,
//morphological operations
//dilation
Mat dilated = new Mat(bmpImg.getWidth(),bmpImg.getHeight(), CvType.CV_8UC1);
Imgproc.dilate(threshed, dilated, Imgproc.getStructuringElement(Imgproc.MORPH_ELLIPSE, new org.opencv.core.Size (16, 16)));
Utils.matToBitmap(dilated, bmpImg);
//write bitmap
bool = Highgui.imwrite(imgPath + "dilated.jpg", dilated);
Toast.makeText(this, "Dilated image saved!", Toast.LENGTH_SHORT).show();
//erosion
Mat eroded = new Mat(bmpImg.getWidth(),bmpImg.getHeight(), CvType.CV_8UC1);
Imgproc.erode(dilated, eroded, Imgproc.getStructuringElement(Imgproc.MORPH_ELLIPSE, new org.opencv.core.Size(15, 15)));
Utils.matToBitmap(eroded, bmpImg);
//write bitmap
bool = Highgui.imwrite(imgPath + "eroded.jpg", eroded);
Toast.makeText(this, "Eroded image saved!", Toast.LENGTH_SHORT).show();
Parce que parfois ma M & Mme pourrait être juste à côté de l'autre! ;)
J'ai aussi essayé d'utiliser des cercles Hough, mais le résultat est très peu fiable (testé avec des images de pièces de monnaie, ainsi que des pièces réelles)
Voici le code,
//hough circles
Mat circles = new Mat();
// parameters
int iCannyUpperThreshold = 100;
int iMinRadius = 20;
int iMaxRadius = 400;
int iAccumulator = 100;
Imgproc.HoughCircles(gray, circles, Imgproc.CV_HOUGH_GRADIENT,
1.0, gray.rows()/8, iCannyUpperThreshold, iAccumulator,
iMinRadius, iMaxRadius);
// draw
if (circles.cols() > 0)
{
Toast.makeText(this, "Coins : " +circles.cols() , Toast.LENGTH_LONG).show();
}
else
{
Toast.makeText(this, "No coins found", Toast.LENGTH_LONG).show();
}
Le problème avec cette approche est que l'algorithme est limité aux cercles parfaits seulement (AFAIK). Donc, ça ne marche pas bien quand j'essaie de numériser et de compter M & Ms ou des pièces sur mon bureau (car l'angle de l'appareil change). Avec cette approche, parfois je reçois moins de non. de pièces de monnaie détectées et parfois plus (je ne comprends pas pourquoi plus ??). En scannant cette image, l'application affiche parfois 19 pièces et parfois 38 pièces comptées ... Je sais qu'il y a d'autres caractéristiques qui peuvent être détectées comme des cercles mais je ne comprends absolument pas pourquoi 38 ..?
Alors mes questions ...
- Y at-il une meilleure façon de remplir les trous sans se joindre blobs adjacents?
- Comment compter le nombre d'objets avec précision? Je ne veux pas limiter mon application à ne compter que les cercles avec l'approche HoughCircles.
FYI: OpenCV-2.4.9-android-sdk. Veuillez garder à l'esprit que je suis un débutant dans OpenCV et Android aussi.
Toute aide est très appréciée.
Merci & À la votre!
Jainam
Avez-vous regardé ici http://stackoverflow.com/questions/1716274/fill-the-holes-in-opencv?rq= 1 ? –
Un simple seuillage Otsu peut fonctionner car les arrière-plans des exemples d'images ne sont pas complexes. – dhanushka