Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/210.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android OpenCV速度交通标志检测_Android_Opencv_Detection_Traffic_Hsv - Fatal编程技术网

Android OpenCV速度交通标志检测

Android OpenCV速度交通标志检测,android,opencv,detection,traffic,hsv,Android,Opencv,Detection,Traffic,Hsv,我在使用Android版opencv 2.4检测速度交通标志时遇到问题。 我做了以下工作: “捕获帧->将其转换为HSV->提取红色区域->使用椭圆检测检测标志” 到目前为止,椭圆检测工作完美,只要图片质量好。 但正如你们在下面的图片中看到的,我认为,由于画框质量差,红色提取不起作用 将原始图像转换为HSV: Imgproc.cvtColor(this.source, this.source, Imgproc.COLOR_RGB2HSV, 3); Core.inRange(this.sourc

我在使用Android版opencv 2.4检测速度交通标志时遇到问题。 我做了以下工作:

“捕获帧->将其转换为HSV->提取红色区域->使用椭圆检测检测标志”

到目前为止,椭圆检测工作完美,只要图片质量好。 但正如你们在下面的图片中看到的,我认为,由于画框质量差,红色提取不起作用

将原始图像转换为HSV:

Imgproc.cvtColor(this.source, this.source, Imgproc.COLOR_RGB2HSV, 3);
Core.inRange(this.source, new Scalar(this.h,this.s,this.v), new Scalar(230,180,180), this.source);
private void findEllipses(Mat input){
Mat thresholdOutput = new Mat();
int thresh = 150;

List<MatOfPoint> contours = new ArrayList<MatOfPoint>();
MatOfInt4 hierarchy = new MatOfInt4();

Imgproc.threshold(source, thresholdOutput, thresh, 255, Imgproc.THRESH_BINARY);
//Imgproc.Canny(source, thresholdOutput, 50, 180);
Imgproc.findContours(source, contours, hierarchy, Imgproc.RETR_LIST, Imgproc.CHAIN_APPROX_SIMPLE);
RotatedRect minEllipse[] = new RotatedRect[contours.size()];

for(int i=0; i<contours.size();i++){
    MatOfPoint2f temp=new MatOfPoint2f(contours.get(i).toArray());

    if(temp.size().height > minEllipseSize && temp.size().height < maxEllipseSize){
        double a = Imgproc.fitEllipse(temp).size.height;
        double b = Imgproc.fitEllipse(temp).size.width;
        if(Math.abs(a - b) < 10)
            minEllipse[i] = Imgproc.fitEllipse(temp);
    }
}
detectedObjects.clear();
for( int i = 0; i< contours.size(); i++ ){
    Scalar color = new Scalar(180, 255, 180);
    if(minEllipse[i] != null){
        detectedObjects.add(new DetectedObject(minEllipse[i].center));
        DetectedObject detectedObj = new DetectedObject(minEllipse[i].center);
        Core.ellipse(source, minEllipse[i], color, 2, 8);
    }
}
提取红色:

Imgproc.cvtColor(this.source, this.source, Imgproc.COLOR_RGB2HSV, 3);
Core.inRange(this.source, new Scalar(this.h,this.s,this.v), new Scalar(230,180,180), this.source);
private void findEllipses(Mat input){
Mat thresholdOutput = new Mat();
int thresh = 150;

List<MatOfPoint> contours = new ArrayList<MatOfPoint>();
MatOfInt4 hierarchy = new MatOfInt4();

Imgproc.threshold(source, thresholdOutput, thresh, 255, Imgproc.THRESH_BINARY);
//Imgproc.Canny(source, thresholdOutput, 50, 180);
Imgproc.findContours(source, contours, hierarchy, Imgproc.RETR_LIST, Imgproc.CHAIN_APPROX_SIMPLE);
RotatedRect minEllipse[] = new RotatedRect[contours.size()];

for(int i=0; i<contours.size();i++){
    MatOfPoint2f temp=new MatOfPoint2f(contours.get(i).toArray());

    if(temp.size().height > minEllipseSize && temp.size().height < maxEllipseSize){
        double a = Imgproc.fitEllipse(temp).size.height;
        double b = Imgproc.fitEllipse(temp).size.width;
        if(Math.abs(a - b) < 10)
            minEllipse[i] = Imgproc.fitEllipse(temp);
    }
}
detectedObjects.clear();
for( int i = 0; i< contours.size(); i++ ){
    Scalar color = new Scalar(180, 255, 180);
    if(minEllipse[i] != null){
        detectedObjects.add(new DetectedObject(minEllipse[i].center));
        DetectedObject detectedObj = new DetectedObject(minEllipse[i].center);
        Core.ellipse(source, minEllipse[i], color, 2, 8);
    }
}
所以我的问题是,有没有其他方法可以检测像这样的交通标志,或者从中提取红色区域,顺便说一句,红色区域可能非常微弱,就像上一张图片一样?

这是原始图像:

这将转换为HSV,因为您可以看到红色区域与附近树木的颜色相同。这就是为什么我应该知道它是红色的,但我不能

转换为HSV:

这是用红色提取的。若颜色是正确的,我应该得到几乎完美的圆形/椭圆围绕符号,但由于错误的颜色,它是不完整的

提取后的结果:

椭圆方法:

Imgproc.cvtColor(this.source, this.source, Imgproc.COLOR_RGB2HSV, 3);
Core.inRange(this.source, new Scalar(this.h,this.s,this.v), new Scalar(230,180,180), this.source);
private void findEllipses(Mat input){
Mat thresholdOutput = new Mat();
int thresh = 150;

List<MatOfPoint> contours = new ArrayList<MatOfPoint>();
MatOfInt4 hierarchy = new MatOfInt4();

Imgproc.threshold(source, thresholdOutput, thresh, 255, Imgproc.THRESH_BINARY);
//Imgproc.Canny(source, thresholdOutput, 50, 180);
Imgproc.findContours(source, contours, hierarchy, Imgproc.RETR_LIST, Imgproc.CHAIN_APPROX_SIMPLE);
RotatedRect minEllipse[] = new RotatedRect[contours.size()];

for(int i=0; i<contours.size();i++){
    MatOfPoint2f temp=new MatOfPoint2f(contours.get(i).toArray());

    if(temp.size().height > minEllipseSize && temp.size().height < maxEllipseSize){
        double a = Imgproc.fitEllipse(temp).size.height;
        double b = Imgproc.fitEllipse(temp).size.width;
        if(Math.abs(a - b) < 10)
            minEllipse[i] = Imgproc.fitEllipse(temp);
    }
}
detectedObjects.clear();
for( int i = 0; i< contours.size(); i++ ){
    Scalar color = new Scalar(180, 255, 180);
    if(minEllipse[i] != null){
        detectedObjects.add(new DetectedObject(minEllipse[i].center));
        DetectedObject detectedObj = new DetectedObject(minEllipse[i].center);
        Core.ellipse(source, minEllipse[i], color, 2, 8);
    }
}
private void findEllipses(Mat输入){
Mat阈值输出=新Mat();
int thresh=150;
列表等高线=新的ArrayList();
MatOfInt4层次结构=新的MatOfInt4();
Imgproc.threshold(源,thresholdOutput,threshold,255,Imgproc.threshold\u二进制);
//Imgproc.Canny(源,阈值输出,50,180);
Imgproc.findContours(源、轮廓、层次、Imgproc.RETR\u列表、Imgproc.CHAIN\u近似\u简单);
RotatedRect minEllipse[]=新的RotatedRect[contours.size()];
对于(int i=0;i minellipseize&&temp.size().height
}

问题符号:

您可以查阅交通标志检测方法和步骤

您将看到有两种方法可以实现这一点:

  • 基于颜色(如您现在所做的)
  • 基于形状
  • 根据我的经验,我发现基于形状的方法非常有效,因为在不同的照明条件、相机质量等条件下,颜色可能会发生很大变化

    因为你需要检测速度交通标志,我假设它总是圆形的,你可以使用椭圆检测器来找到你图像中的所有圆形物体,然后应用一些验证来确定它是否是交通标志

    为什么要检测椭圆

    既然你在找透视扭曲的圆,实际上你在找椭圆。实时椭圆检测是一个有趣(尽管有限)的研究课题。我将向您指出2篇有C++源代码的论文(可以通过本地JNI调用在您的应用程序中使用):

  • L.Libuda,I.Grothues,K.-F.Kraiss,数字图像中的椭圆检测 使用几何特征的数据,见:J.Braz,A.Ranchordas,H.Arajo, J.Jorge(编辑),《计算机图形学和计算机视觉的进展》, 计算机与信息科学通信第4卷, 施普林格柏林海德堡,2007年,第229-239页

  • M.Fornaciari,A.Prati,R.Cucchiara, “用于嵌入式视觉应用的快速有效椭圆检测器”,模式识别,2014


  • 更新

    我在没有任何预处理的情况下尝试了这个方法。您可以看到,至少红色边框的标志检测得非常好:

    私有无效findEllipses(Mat输入){
    Mat阈值输出=新Mat();
    int thresh=150;
    列表等高线=新的ArrayList();
    MatOfInt4层次结构=新的MatOfInt4();
    Imgproc.threshold(源,thresholdOutput,threshold,255,Imgproc.threshold\u二进制);
    //Imgproc.Canny(源,阈值输出,50,180);
    Imgproc.findContours(源、轮廓、层次、Imgproc.RETR\u列表、Imgproc.CHAIN\u近似\u简单);
    //源=阈值输出;
    RotatedRect minEllipse[]=新的RotatedRect[contours.size()];
    对于(int i=0;i minellipseize&&temp.size().height
    引用您的文本:

    这将转换为HSV,因为您可以看到红色区域看起来是相同的颜色 就像附近的树一样。这就是为什么我应该知道它是红色的,但我不能

    我想向您展示我对您所做的基本操作的结果(简单的操作应该可以很容易地转移到android openCV):

    //转换为HSV
    cv::Mat-hsv;
    cv::cvtColor(输入,hsv,cv_BGR2HSV);
    矢量信道;
    cv::分割(hsv,通道);
    //opencv=色调值除以2以适应8位范围
    浮动红1=25/2.0f;
    //红色的一部分在范围的开始处,一部分在范围的结束处(我假设0°到25°和335°到360°)
    浮动红2=(360-25)/2.0f;
    //计算两个t