opencv 霍夫变换cvHoughLines2 cvHoughCircles cvApproxPoly

opencv cvHoughLines2 cvHoughCircles cvApproxPoly

demo: http://download.csdn.net/detail/keen_zuxwang/9852591

霍夫变换是图像变换中的经典手段之一,主要用来从图像中分离出具有某种相同特征的几何形状(如,直线,圆等).霍夫变换的两个算法:
标准霍夫变换(SHT)
累计概率霍夫变换(PPHT)

霍夫圆变换与直线变换大体上是类似的,累加平面会被三维累加容器代替,(x,y,r),x,y确定圆心,r确定半径,但这意味着需要大量内存速度较慢,OpenCV通过一个比较灵活的霍夫梯度法来解决圆变换问题,利用到cvSobel

基于霍夫变换(Hough Transform)在二值图像中寻找直线cvHoughLines2
基于霍夫变换(Hough Transform)的找圆函数cvHoughCircles

/* Variants of a Hough transform */
enum
{
    CV_HOUGH_STANDARD =0,
    CV_HOUGH_PROBABILISTIC =1,
    CV_HOUGH_MULTI_SCALE =2,
    CV_HOUGH_GRADIENT =3
};

/* Finds lines on binary image using one of several methods.
   line_storage is either memory storage or 1 x <max number of lines> CvMat, its
   number of columns is changed by the function.
   method is one of CV_HOUGH_*;
   rho, theta and threshold are used for each of those methods;
   param1 ~ line length, param2 ~ line gap - for probabilistic,
   param1 ~ srn, param2 ~ stn - for multi-scale */
CVAPI(CvSeq*)  cvHoughLines2( CvArr* image, void* line_storage, int method,
                              double rho, double theta, int threshold,
                              double param1 CV_DEFAULT(0), double param2 CV_DEFAULT(0));

image
输入 8-比特、单通道 (二值) 图像,当用CV_HOUGH_PROBABILISTIC办法检测的时辰其内容会被函数改变。
line_storage
检测到的线段存储仓. 可所以内存存储仓 (此种景象下,一个线段序列在存储仓中被创建,并且由函数返回),或者是包含线段参数的特别类型(见下面)的具有单行/单列的矩阵(CvMat*)。矩阵头为函数所批改,使得它的 cols/rows 将包含一组检测到的线段。若是 line_storage 是矩阵,而实际线段的数量跨越矩阵尺寸,那么最大可能数量标线段被返回(线段没有遵守长度、可托度或其它指标排序).
method
Hough 变换变量,是下面变量的此中之一:
CV_HOUGH_STANDARD - 传统或标准 Hough 变换. 每一个线段由两个浮点数 (ρ, θ) 默示,此中 ρ 是直线与原点 (0,0) 之间的间隔,θ 线段与 x-轴之间的夹角。是以,矩阵类型必须是 CV_32FC2 type.
CV_HOUGH_PROBABILISTIC - 概率 Hough 变换(若是图像包含一些长的线性分别,则效力更高). 它返回线段分别而不是全部线段。每个分别用出发点和终点来默示,所以矩阵(或创建的序列)类型是 CV_32SC4.
CV_HOUGH_MULTI_SCALE - 传统 Hough 变换的多标准变种。线段的编码体式格式与 CV_HOUGH_STANDARD 的一致。
rho
与象素相干单位的间隔精度
theta
弧度测量的角度精度
threshold
阈值参数。若是响应的累计值大于 threshold, 则函数返回的这个线段.
param1
第一个办法相干的参数:
对传统 Hough 变换,不应用(0).
对概率 Hough 变换,它是最小线段长度.
对多标准 Hough 变换,它是间隔精度 rho 的分母 (大致的间隔精度是 rho 而正确的应当是 rho / param1 ).
param2
第二个办法相干参数:
对传统 Hough 变换,不应用 (0).
对概率 Hough 变换,这个参数默示在同一条直线长进行碎线段连接的最大间隔值(gap), 即当同一条直线上的两条碎线段之间的间隔小于param2时,将其合二为一。
对多标准 Hough 变换,它是角度精度 theta 的分母 (大致的角度精度是 theta 而正确的角度应当是 theta / param2)
  

/* Finds circles in the image */
CVAPI(CvSeq*) cvHoughCircles( CvArr* image, void* circle_storage,
                              int method, double dp, double min_dist,
                              double param1 CV_DEFAULT(100),
                              double param2 CV_DEFAULT(100),
                              int min_radius CV_DEFAULT(0),
                              int max_radius CV_DEFAULT(0));

image
输入8bit(灰度)图像,其内容可被函数所改变
circle_storage
检测到的圆存储仓,可以是内存存储仓 (此种情况下,一个线段序列在存储仓中被创建,并且由函数返回)或者是包含圆参数的特殊类型的具有单行/单列的CV_32FC3型矩阵(CvMat*). 矩阵头为函数所修改,使得它的 cols/rows 将包含一组检测到的圆。如果 circle_storage 是矩阵,而实际圆的数目超过矩阵尺寸,那么最大可能数目的圆被返回,每个圆由三个浮点数表示:圆心坐标(x,y)和半径.).
method:Hough 变换方式,只支持CV_HOUGH_GRADIENT
dp:寻找圆弧圆心的累计分辨率,这个参数允许创建一个比输入图像分辨率低的累加器。(这样做是因为有理由认为图像中存在的圆会自然降低到与图像宽高相同数量的范畴)。如果dp设置为1,则分辨率是相同的;如果设置为更大的值(比如2),累加器的分辨率受此影响会变小(此情况下为一半)。dp的值不能比1小。
min_dist:该参数是让算法能明显区分的两个不同圆之间的最小距离。
param1:用于Canny的边缘阀值上限,下限被置为上限的一半。
param2:累加器的阀值。
min_radius:最小圆半径。
max_radius:最大圆半径

//多边形逼近
CVAPI(CvSeq*)  cvApproxPoly( const void* src_seq,
                             int header_size, CvMemStorage* storage,
                             int method, double parameter,
                             int parameter2 CV_DEFAULT(0));

使用多边形去逼近轮廓,使顶点数目变少。
CvSeq* 返回值对应第一个 轮廓(可用h_next和v_next访问其他轮廓)
src_seq 要处理的目标序列
header_size 为返回结果指定头结构大小
storage 为返回结果指定新的内存存储器
method 算法:目前只有CV_POLY_APPOX_DP
parameter 逼近算法参数,指定逼近精度,曲线1、n
parameter2 逼近算法参数。若为0,只处理src_seq指向的轮廓。1则处理整个双向链表中的所有轮廓

Sobel
使用扩展 Sobel 算子计算一阶、二阶、三阶或混合图像差分

//! applies generalized Sobel operator to the image
CV_EXPORTS_W void Sobel( InputArray src, OutputArray dst, int ddepth,
                         int dx, int dy, int ksize=3,
                         double scale=1, double delta=0,
                         int borderType=BORDER_DEFAULT );

/* Calculates an image derivative using generalized Sobel
   (aperture_size = 1,3,5,7) or Scharr (aperture_size = -1) operator.
   Scharr can be used only for the first dx or dy derivative */
CVAPI(void) cvSobel( const CvArr* src, CvArr* dst,
                    int xorder, int yorder,
                    int aperture_size CV_DEFAULT(3)); 

src
输入图像
dst
输出图像, 如果源图像src是8位的,为避免溢出,目标图像的深度必须是IPL_DEPTH_16S
xorder
x方向上的差分阶数
yorder
y方向上的差分阶数
aperture_size
扩展Sobel核的大小,必须是1, 3, 5 或 7。
除了尺寸为 1,其它情况下,aperture_size×aperture_size可分离内核将用来计算差分。
aperture_size=1,使用3x1或1x3内核(不进行高斯平滑操作)。
aperture_size=-1, 对应3x3 Scharr滤波器(比3x3 Sobel滤波更精确)

JNI:
houghline.cpp

#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <jni.h>
#include <android/log.h>
#include <iostream>
#include <fstream>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/objdetect/objdetect.hpp>
#include "opencv2/features2d/features2d.hpp"
#include "opencv2/calib3d/calib3d.hpp"
#include "opencv2/imgproc/types_c.h"
#include "opencv2/imgproc/imgproc_c.h"
#include "opencv2/video/tracking.hpp"
#include "opencv2/video/video.hpp"
#include <opencv2/ml/ml.hpp>

using namespace std;
using namespace cv;

#define LOG_TAG "FeatureTest"
#define LOGD(...) ((void)__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__))

#ifdef __cplusplus
extern "C" {
#endif

#define BYTE unsigned char

void HoughLine(IplImage* pImg)  //Hough变换提取直线
{
    IplImage* pGray=cvCreateImage(cvSize(pImg->width,pImg->height),IPL_DEPTH_8U,1);
    cvCvtColor(pImg,pGray,CV_BGR2GRAY);//提取图像边缘点
    cvCanny(pGray,pGray,10,150);

    CvMemStorage* pMem=cvCreateMemStorage(0);//分配存储直线的内存
    CvSeq* pLineSeq=cvHoughLines2(pGray,pMem,CV_HOUGH_PROBABILISTIC,1,CV_PI/180,50,5,2);//Hough变换提取直线100 100,30
    if (pLineSeq)
    {
        int i;
        for (i=0;i<MIN(pLineSeq->total,100);i++)//显示不超过100条的直线
        {
            CvPoint* line=(CvPoint*)cvGetSeqElem(pLineSeq,i);//获取直线参数
            cvLine(pImg,line[0],line[1],CV_RGB(255,0,0),2);//显示直线
        }
    }
    cvReleaseMemStorage(&pMem);//释放内存
    //cvShowImage("Canny Edge",pGray);///显示边缘点图像
    cvReleaseImage(&pGray);
}

void HoughCircle(IplImage* pImg)   //Hough变换提取圆
{
    IplImage* pGray=cvCreateImage(cvSize(pImg->width,pImg->height),IPL_DEPTH_8U,1);
    cvCvtColor(pImg,pGray,CV_BGR2GRAY);   //转换为灰度图像
    cvSmooth(pGray, pGray,CV_GAUSSIAN, 3, 3);   //高斯平滑滤波

    int nCannyThresholdMax=150;   //canny算子的高阈值
    CvMemStorage* pMem=cvCreateMemStorage(0);   //存储圆参数的内存 CV_HOUGH_GRADIENT
    CvSeq* pCircleSeq=cvHoughCircles(pGray,pMem, CV_HOUGH_GRADIENT, 2,pGray->width/50,
            nCannyThresholdMax,100,pGray->width/50,pGray->width/2);

    LOGD("         HoughCircle = %d      !", pCircleSeq->total);

    for (int i=0;i<MIN(10,pCircleSeq->total);i++)   //最多存储十个圆
    {
        float* p=(float*)cvGetSeqElem(pCircleSeq,i);
        cvCircle(pImg,cvPoint(p[0]+0.5,p[1]+0.5),(int)(p[2]+0.5),CV_RGB(255,0,255),3);
    }

    cvReleaseMemStorage(&pMem);   //释放内存
    cvCanny(pGray,pGray,nCannyThresholdMax/2,nCannyThresholdMax);
    //cvShowImage("Canny Circle",pGray);   //同步显示边缘点
    cvReleaseImage(&pGray);
}

void EqualizeGray(IplImage* pImg)  //直方图均衡化
{
    IplImage* pGray=cvCreateImage(cvSize(pImg->width,pImg->height),IPL_DEPTH_8U,1);
    cvCvtColor(pImg,pGray,CV_BGR2GRAY);
    pGray->origin=pImg->origin;
    //cvShowImage("Gray Image",pGray);

    IplImage* pEqualizedImg=cvCreateImage(cvSize(pImg->width,pImg->height),IPL_DEPTH_8U,1);
    cvEqualizeHist(pGray, pEqualizedImg);
    //cvShowImage("Equalize Image",pEqualizedImg);
    cvReleaseImage(&pGray);
}

void cvFindContours2(Mat pImg)   //颜色识别 轮廓检测  IplImage* pImg
{
    Mat pGray;
    cvtColor(pImg, pGray, CV_BGR2GRAY); // 1、灰度图

    blur(pGray, pGray, Size(5,5)); //2、 均值滤波

    //Finde vertical edges. Car plates have high density of vertical lines
    Mat img_sobel;
    Sobel(pGray, img_sobel, CV_8U, 1, 1, 3, 1, 0, BORDER_DEFAULT);// 3、sobel 边缘提取 xorder=1,yorder=0,kernelsize=3

    Mat img_threshold;
    threshold(img_sobel, img_threshold, 0, 255, CV_THRESH_OTSU); // 4、二值化  img_sobel CV_THRESH_BINARY

    //Morphplogic operation close:remove blank spaces and connect all regions that have a high number of edges
    Mat element = getStructuringElement(MORPH_RECT, Size(17, 3) ); // 5、高级形态学变化,闭操作
    morphologyEx(img_threshold, img_threshold, CV_MOP_CLOSE, element);

    //Find 轮廓 of possibles plates
    vector< vector< Point> > contours; // a vector of contours
    findContours(img_threshold, contours,
                CV_RETR_EXTERNAL, // 提取外部轮廓
                CV_CHAIN_APPROX_NONE); // all pixels of each contours

    LOGD("         contours.size() = %d      !", contours.size());
    drawContours(pImg, contours, -1, Scalar(0,0,255), 2);

}

JNIEXPORT jlong JNICALL Java_com_example_houghline_MainActivity_doThreshold(JNIEnv *env, jclass clz, jlong imageGray)
{
    Mat pImg = Mat(*(Mat*)imageGray);
    Mat pGray;
    cvtColor(pImg, pGray, CV_BGR2GRAY); // 1、灰度图
    //equalizeHist(pGray, pGray); // 2、直方图均衡化  CV_EXPORTS_W void equalizeHist( InputArray src, OutputArray dst );

    blur(pGray, pGray, Size(5,5)); //2、 均值滤波

    //Mat img_sobel;
    //Sobel(pGray, img_sobel, CV_8U, 1, 1, 3, 1, 0, BORDER_DEFAULT);// 3、sobel 边缘提取 xorder=1,yorder=1,kernelsize=3

    Mat img_threshold;
    threshold(pGray, img_threshold, 0, 255, CV_THRESH_OTSU); // 4、二值化  img_sobel CV_THRESH_BINARY_INV CV_THRESH_OTSU

    Mat *hist = new Mat(img_threshold);
    return (jlong) hist;
}

JNIEXPORT jlong JNICALL Java_com_example_houghline_MainActivity_doSobel(JNIEnv *env, jclass clz, jlong imageGray)
{
    Mat imageMat = Mat(*(Mat*)imageGray);
    IplImage  temp_src = imageMat;
    IplImage* imageg = &temp_src;

    EqualizeGray(imageg); //1、 直方图均衡化
    //IPL_DEPTH_16S
    IplImage *pImgDes0 = cvCreateImage(cvSize(imageg->width, imageg->height), imageg->depth, imageg->nChannels);
    cvSobel(imageg,pImgDes0,0,1,-1); //2、x方向的边缘
    cvSobel(imageg,pImgDes0,1,0,-1); //3、y方向的边缘
    //cvSobel(imageg,pImgDes0,1,0,-1); //Scharr滤波器
    cvConvertScaleAbs(pImgDes0,imageg); // 4、将16S图像转化成8bit图像,无符号整形

    //EqualizeGray(imageg);  // 直方图均衡化
    //cvCanny(imageg,imageg,10,150,3);   //canny算子只能处理灰度图像,3参数分别为sigma,dRatHigh,dRatLow

    Mat *hist = new Mat(imageg);
    return (jlong) hist;
}

JNIEXPORT jlong JNICALL Java_com_example_houghline_MainActivity_doHough(JNIEnv *env, jclass clz, jlong imageGray, jint type_num)
{
    LOGD("          type_num = %d       !",type_num);
    Mat imageMat = Mat(*(Mat*)imageGray);
    IplImage  temp_src = imageMat;
    IplImage* imageg = &temp_src;

    if(type_num==0){
        HoughLine(imageg);
    }else if(type_num==1){

        HoughCircle(imageg);
    }else if(type_num==2){
        //cvFindContours2(imageg);
        cvFindContours2(imageMat);
        //EqualizeGray(imageg);
        Mat *hist = new Mat(imageMat);
        return (jlong) hist;
    }
    Mat *hist = new Mat(imageg);
    return (jlong) hist;
}

#ifdef __cplusplus
}
#endif

houghline:
这里写图片描述

houghcircle:
这里写图片描述

contours:
这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值