我试图在下面3张图片的中间找到数字的边界框。
这是我尝试使用的3张示例卡片。
我使用的代码基于(几乎完整副本)第一个答案here中提供的代码,虽然转换为Java(C ++中的答案很好)并且添加了大小的参数要合并的轮廓(在我的代码中定义为sizeHorizonal和sizeVertical),这是我在下面的图片中玩的两个参数。
MatOfPoint2f approxCurve = new MatOfPoint2f();
Mat imgMAT = new Mat();
Utils.bitmapToMat(bmp32, imgMAT);
Mat grad = new Mat();
Imgproc.cvtColor(imgMAT, grad, Imgproc.COLOR_BGR2GRAY);
Mat img_sobel = new Mat();
Mat img_threshold = new Mat();
Imgproc.Sobel(grad, img_sobel, CvType.CV_8U, 1, 0, 3, 1, 0, Core.BORDER_DEFAULT);
Imgproc.threshold(img_sobel, img_threshold, 0, 255, Imgproc.THRESH_OTSU + Imgproc.THRESH_BINARY);
Mat element = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(sizeHorizontal, sizeVertical));
Imgproc.morphologyEx(img_threshold, img_threshold, Imgproc.MORPH_CLOSE, element);
Imgproc.cvtColor(imgMAT, imgMAT, Imgproc.COLOR_BGR2GRAY);
List<MatOfPoint> contours = new ArrayList<>();
Imgproc.findContours(img_threshold, contours, new Mat(), Imgproc.RETR_CCOMP, Imgproc.CHAIN_APPROX_SIMPLE, new org.opencv.core.Point(0, 0));
for (int i = 0; i < contours.size(); i++) {
//Convert contours(i) from MatOfPoint to MatOfPoint2f
MatOfPoint2f contour2f = new MatOfPoint2f( contours.get(i).toArray() );
//Processing on mMOP2f1 which is in type MatOfPoint2f
double approxDistance = Imgproc.arcLength(contour2f, true)*0.02;
Imgproc.approxPolyDP(contour2f, approxCurve, approxDistance, true);
//Convert back to MatOfPoint
MatOfPoint points = new MatOfPoint( approxCurve.toArray() );
// Get bounding rect of contour
org.opencv.core.Rect rect = Imgproc.boundingRect(points);
Imgproc.rectangle(imgMAT, rect.tl(), rect.br(), new Scalar(0, 255, 0), 2);
}
我有单独的数字部分轮廓,但我找不到一种方法来隔离我想要的轮廓。这里是使用尺寸输入参数绘制轮廓的区域。正如你可以看到的第二张图片,这是完全按照我想要的方式工作,并且轮廓整个数字,而不是每个部分。
1:大小参数输入:17,5
2:大小参数输入:23,7
3:大小参数输入:23,13
所以,我需要帮助的事情:
我考虑过采用与给定宽高比相匹配的轮廓并裁剪到包含所有这些轮廓线的边界框,但还有其他周围轮廓具有相似的比例。
如果没有尝试所有3个尺寸的输入并查看给出预期轮廓的内容,我可以使用流行的颜色作为卡片类型的指示器,然后使用此卡片类型的参数。但是,任何其他建议都会有所帮助,因为我觉得有更好的方法可以做到这一点。
非常感谢!
答案 0 :(得分:2)
在我繁忙的日程中,我可以帮助你灭绝一些。请找到下面的代码,它将帮助您获得前两张图片。为第三张图像微调。只需使用形态学操作即可获得所需的输出。
//#include "stdafx.h"
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>
#include "tchar.h"
using namespace cv;
using namespace std;
#define INPUT_FILE "p.jpg"
#define OUTPUT_FOLDER_PATH string("")
int _tmain(int argc, _TCHAR* argv[])
{
Mat large = imread(INPUT_FILE);
Mat rgb;
// downsample and use it for processing
pyrDown(large, rgb);
Mat small;
cvtColor(rgb, small, CV_BGR2GRAY);
// morphological gradient
Mat grad;
Mat morphKernel = getStructuringElement(MORPH_ELLIPSE, Size(2, 2));
Mat morphKernel1 = getStructuringElement(MORPH_ELLIPSE, Size(1, 1));
morphologyEx(small, grad, MORPH_GRADIENT, morphKernel);
// binarize
Mat bw;
threshold(grad, bw, 5.0, 50.0, THRESH_BINARY | THRESH_OTSU);
// connect horizontally oriented regions
Mat connected;
morphKernel = getStructuringElement(MORPH_RECT, Size(9, 1));
morphologyEx(bw, connected, MORPH_CLOSE, morphKernel);
morphologyEx(bw, connected, MORPH_OPEN, morphKernel1);
morphologyEx(connected, connected, MORPH_CLOSE, morphKernel);
morphologyEx(connected, connected, MORPH_CLOSE, morphKernel);
morphologyEx(connected, connected, MORPH_CLOSE, morphKernel);
// find contours
Mat mask = Mat::zeros(bw.size(), CV_8UC1);
vector<vector<Point>> contours;
vector<Vec4i> hierarchy;
findContours(connected, contours, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));
// filter contours
int y=0;
for(int idx = 0; idx >= 0; idx = hierarchy[idx][0])
{
Rect rect = boundingRect(contours[idx]);
Mat maskROI(mask, rect);
maskROI = Scalar(0, 0, 0);
// fill the contour
drawContours(mask, contours, idx, Scalar(255, 255, 255), CV_FILLED);
double a=contourArea( contours[idx],false);
if(a> 575)
{
rectangle(rgb, rect, Scalar(0, 255, 0), 2);
y++;
}
imshow("Result1",rgb);
}
cout<<" The number of elements"<<y<< endl;
imshow("Result",mask);
imwrite(OUTPUT_FOLDER_PATH + string("rgb.jpg"), rgb);
waitKey(0);
return 0;
}