我是 OpenCV 的新手,正在尝试计算图像中对象的数量。我在使用 MATLAB Image Processing Toolbox 之前已经完成了这项工作,并且在 OpenCV (Android) 中也采用了相同的方法。
第一步是将图像转换为灰度。然后对其进行阈值化,然后计算 blob 的数量。在 Matlab 中有一个命令 - “bwlabel”,它给出了 blob 的数量。我在 OpenCV 中找不到这样的东西(同样,我是 OpenCV 和 Android 的菜鸟)。
这是我的代码,
//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();
在下一步中,我尝试使用膨胀和腐蚀来填充孔和字母,但斑点会相互连接,最终会给出错误的计数。在调整膨胀和腐蚀参数时,需要在填充孔和使斑点相互连接之间进行权衡。
这是代码,
//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();
因为有时我的 M&Ms 可能就在旁边!;)
我也尝试使用 Hough Circles,但结果非常不可靠(用硬币图像和真实硬币测试)
这是代码,
//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();
}
这种方法的问题在于该算法仅限于完美的圆(AFAIK)。因此,当我尝试扫描和计算桌上的 M&Ms 或硬币时(因为设备的角度发生了变化),它效果不佳。使用这种方法,有时我得到的结果更少。检测到的硬币数量,有时甚至更多(我不明白为什么更多??)。
在扫描此图像时,该应用程序有时会显示 19 个硬币,有时会显示 38 个硬币......我知道还有其他特征可能会被检测为圆圈,但我完全不明白为什么 38..?
所以我的问题...
- 有没有更好的方法来填充孔而不连接相邻的斑点?
- 如何准确计算对象的数量?我不想将我的应用程序限制为仅使用 HoughCircles 方法计算圆圈。
仅供参考:OpenCV-2.4.9-android-sdk。请记住,我也是 OpenCV 和 Android 的新手。
任何帮助深表感谢。
谢谢和干杯!
耆南