Java 使用OpenCV查找图像上数字的边界框 我试图在下面的3幅图像中间找到数字的包围盒。
这里有3张我尝试使用的示例卡 <>我使用的代码是第一个答案中提供的代码的基础(几乎是完整的副本),虽然转换为java(C++中的答案很好),并且为轮廓合并的大小添加了参数(在我的代码中定义为sisial-and sisiValigic),这是我在下面的图像中播放的两个参数。Java 使用OpenCV查找图像上数字的边界框 我试图在下面的3幅图像中间找到数字的包围盒。,java,c++,opencv,bounding-box,Java,C++,Opencv,Bounding Box,这里有3张我尝试使用的示例卡 我使用的代码是第一个答案中提供的代码的基础(几乎是完整的副本),虽然转换为java(C++中的答案很好),并且为轮廓合并的大小添加了参数(在我的代码中定义为sisial-and sisiValigic),这是我在下面的图像中播放的两个参数。 MatOfPoint2f approxCurve = new MatOfPoint2f(); Mat imgMAT = new Mat(); Utils.bitmapToMat(bmp32, imgMAT); Mat
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);
}
MatOfPoint2f approxCurve=新的MatOfPoint2f();
Mat imgMAT=新Mat();
比特映射器(bmp32,imgMAT);
材料梯度=新材料();
Imgproc.cvt颜色(imgMAT、grad、Imgproc.COLOR\u bgr2灰色);
Mat img_sobel=新Mat();
Mat img_阈值=新Mat();
Imgproc.Sobel(grad,img_Sobel,CvType.CV_8U,1,0,3,1,0,Core.BORDER_默认值);
Imgproc.threshold(img_sobel,img_threshold,0,255,Imgproc.THRESH_OTSU+Imgproc.THRESH_二进制);
Mat element=Imgproc.getStructuringElement(Imgproc.morp_RECT,新尺寸(水平尺寸,垂直尺寸));
Imgproc.morphologyEx(img_阈值,img_阈值,Imgproc.morp_关闭,元素);
Imgproc.cvt颜色(imgMAT,imgMAT,Imgproc.COLOR_bgr2灰色);
列表等高线=新的ArrayList();
Imgproc.findContours(img_阈值,等高线,new Mat(),Imgproc.RETR_CCOMP,Imgproc.CHAIN_近似值,new org.opencv.core.Point(0,0));
对于(int i=0;i
我已经绘制了不同数量的等高线,但是我找不到一种方法来隔离我想要的等高线。以下是用尺寸输入参数绘制的区域轮廓。正如您在第二张图片中看到的,这正是我想要的,并且已经勾勒出了整个数字,而不是每个部分
1:尺寸参数输入:17,5
2:尺寸参数输入:23,7
3:尺寸参数输入:23,13
因此,我需要在以下方面得到帮助:
隔离中间的四个轮廓并找到将这些轮廓合并到的方法。
我曾考虑过将与给定纵横比匹配的轮廓裁剪到一个包含所有轮廓的边界框中,但也有其他具有类似比例的周围轮廓
//#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;
}
/#包括“stdafx.h”
#包括
#包括
#包括
#包括
#包括“tchar.h”
使用名称空间cv;
使用名称空间std;
#定义输入文件“p.jpg”
#定义输出文件夹路径字符串(“”)
int _tmain(int argc,_TCHAR*argv[]
{
Mat large=imread(输入文件);
Mat-rgb;
//减少采样并将其用于处理
吡咯烷酮(大,rgb);
垫小;
CVT颜色(rgb,小,CV_bgr2灰色);
//形态梯度
垫梯度;
Mat morphKernel=getStructuringElement(变形椭圆,大小(2,2));
Mat morphKernel1=getStructuringElement(变形椭圆,大小(1,1));
形态学(小,梯度,形态梯度,形态核);
//二值化
Mat bw;
阈值(梯度、bw、5.0、50.0、阈值二元、阈值大津);
//连接水平方向的区域
垫子连接;
morphKernel=getStructuringElement(MORPH_RECT,Size(9,1));
morphologyEx(bw,连通,MORPH_-CLOSE,morphKernel);
形态学(bw,连通,形态开放,形态核1);
morphologyEx(连通,连通,MORPH_CLOSE,morphKernel);
morphologyEx(连通,连通,MORPH_CLOSE,morphKernel);
morphologyEx(连通,连通,MORPH_CLOSE,morphKernel);
//寻找轮廓
Mat mask=Mat::zeros(bw.size(),CV_8UC1);
矢量等值线;
向量层次;
findContours(连通、轮廓、层次、CV_RETR_CCOMP、CV_CHAIN_近似、简单、点(0,0));
//过滤轮廓
int y=0;
对于(int idx=0;idx>=0;idx=hierarchy[idx][0])
{
Rect Rect=boundingRect(等高线[idx]);
Mat maskROI(蒙版,矩形);
maskROI=标量(0,0,0);
//填充轮廓
绘制等高线(遮罩、等高线、idx、标量(255、255、255)、CV_填充);
双a=轮廓面积(轮廓[idx],假);
如果(a>575)
{
矩形(rgb,rect,标量(0,255,0),2);
y++;
}
imshow(“结果1”,rgb);
}
根据图像,似乎总是有4组数字。如果您可以确保图像大部分是水平的,您可以尝试首先水平计数零交叉。它应该在32-64之间。这将允许您水平定位数字的位置。然后执行您现在正在执行的步骤,即使用mor定位斑点它们必须均匀分布。满足这两个条件的元素很少。