精华内容
下载资源
问答
  • 6. 判断圆是否在多边形内 5 7. 求矢量夹角余弦 5 8. 求线段之间夹角 5 9. 判断线段是否相交 6 10.判断线段是否相交但不交在端点处 6 11.求线段所在直线方程 6 12.求直线斜率 7 13.求直线倾斜角 7 14.求点...
  • OpenCV霍夫变换识别

    千次阅读 2015-08-10 11:26:43
    但是cvHoughCircles的效果并不好,会检测出很多并不存在的拟合。因此还需在霍夫变换的基础上限定一些条件,对识别出的进行check。 因为我想要识别的是实心,所以会对霍夫变换后的结果进行判断,圆心周围是否都...

    想用openCV的 cvHoughCircles去识别实心的黑圆。但是cvHoughCircles的效果并不好,会检测出很多并不存在的拟合圆。因此还需在霍夫变换的基础上限定一些条件,对识别出的圆进行check。

    因为我想要识别的是实心圆,因此对霍夫变换后的结果进行判断,圆心周围是否都是黑色的,是否是实心圆。

    还加入了圆度公式对霍夫变换后的结果进行check:圆度D = 4πS/(L*L)。当对象越接近于圆时,圆度D越接近于1。

    加上了这两个check条件后,cvHoughCircles的识别结果,达到了我想要的结果~


    首先选定ROI,再对选定区域进行Canny算子的边缘检测。

    IplImage	*srcBitmap;
    srcBitmap = cvLoadImage(fileNameFull, 1);
    cvCvtColor(srcBitmap, srcBitmap, CV_RGB2GRAY);
    cvThreshold(srcBitmap,srcBitmap,200,255,THRESH_BINARY);
    cvSetImageROI(srcBitmap, cvRect(0, 0, 400, 400));
    //pImg8uOri为原图,pImg8u为边缘检测后的图片
    pImg8uOri = cvCreateImage(cvSize(400, 400), srcBitmap->depth, srcBitmap->nChannels);
    pImg8u = cvCreateImage(cvSize(400, 400), srcBitmap->depth, srcBitmap->nChannels);
    cvCopy(srcBitmap, pImg8uOri, NULL);cvResetImageROI(srcBitmap);cvCanny(pImg8uOri, pImg8u, 1, 2, 3);


    
    

    再对边缘检测后的图片用cvHoughCircles进行找圆,对霍夫变换后的结果进行check。满足条件的则为要找的圆。

    CvSeq * circles=NULL;
    CvMemStorage* storage = cvCreateMemStorage(0);
    circles=cvHoughCircles(pImg8u,storage,CV_HOUGH_GRADIENT,
      					1,   //最小分辨率,应当>=1	
    						//double类型的dp,用来检测圆心的累加器图像的分辨率于输入图像之比的倒数
    						//且此参数允许创建一个比输入图像分辨率低的累加器。
    						//例如,如果dp = 1,累加器和输入图像具有相同的分辨率
    						//如果dp = 2,累加器便有输入图像一半那么大的宽度和高度
    					50,	//pImg8u->height/4,   //该参数是让算法能明显区分的两个不同圆之间的最小距离
    					40,  //用于Canny的边缘阀值上限,下限被置为上限的一半
    					2,  //累加器的阀值
    						//越小就可以检测到更多根本不存在的圆。
    						//越大的话,检测到的圆就越接近完美的圆形
    					10,  //最小圆半径 
    					40	//最大圆半径
     					);
    int k;
    int circleCount = 0;
    double maxD = 0;
    int maxPx = 0;
    int maxPy = 0;
    int maxR = 0;
    for (k=0;k<circles->total;k++){
    	float *p=(float*)cvGetSeqElem(circles,k);
    	if ((cvRound(p[0])-15 < 0) || (cvRound(p[0]) + 15 >399)) continue;
    	if ((cvRound(p[1])-15 < 0) || (cvRound(p[1]) + 15 >399)) continue;
    	//check所找到的圆是否是实心的
    	if (!(isFilled(pImg8uOri,cvRound(p[0]),cvRound(p[1]),15))) continue;
    	int oriCount = 0;
    	int cannyCount = 0;
    	//圆度D = 4πS/(L*L)。当对象越接近于圆时,圆度D越接近于1
    	int xLeft = cvRound(p[0]) - 24;
    	if (xLeft < 0){
    		xLeft = 0;
    	}
    	int xRight = cvRound(p[0]) + 25;
    	if (xRight > 399){
    		xRight = 399;
    	}
    	int yLeft = cvRound(p[1]) - 24;
    	if (yLeft < 0){
    		yLeft = 0;
    	}
    	int yRight = cvRound(p[1]) + 25;
    	if (yRight > 399){
    		yRight = 399;
    	}
    
    	int xCoordinate = 0;
    	int yCoordinate = 0;
    	int rightOri = 0;
    	int rightCanny = 0;
    	for(int x1 = xLeft; x1 < xRight; x1++){
    		for(int y1 = yLeft; y1 < yRight; y1++){
    			CvScalar s1 = cvGet2D(pImg8uOri, y1, x1);
    			if (s1.val[0] < 128){
    				oriCount ++;
    				xCoordinate = xCoordinate + x1;
    				yCoordinate = yCoordinate + y1;					
    			} 
    			CvScalar s2 = cvGet2D(pImg8u, y1, x1);
    			if (s2.val[0] > 128) cannyCount ++;		
    			if (x1 == xRight - 1){
    				if (s1.val[0] < 128){
    					rightOri = rightOri + 1;
    				}
    				if (s2.val[0] > 128){
    					rightCanny = rightCanny + 1;
    				}
    			}
    		}
    		//圆度公式需要算出周长,周长的算法我用的是求边缘检测后的该区域黑点的个数
    		//如果实心区域超出了选取的目标区域,则周长没闭合。需补偿
    		//暂时未考虑上下边超出了目标区域的情况
    		if (x1 == xLeft){
    			if (cannyCount < oriCount){
    				cannyCount = cannyCount + oriCount;
    			}
    		}
    		if (x1 == xRight - 1){
    			if (rightCanny < rightOri) {
    				cannyCount = cannyCount + rightOri;
    			}
    		}
    	}
    	//圆度越大越接近于圆
    	double D = 4 * PI * oriCount/(cannyCount * cannyCount);
    
    	if (D < 0.4 || D >= 1) continue;
    	//根据平均值校准圆心
    	int rectifyX = (double)xCoordinate/(double)oriCount + 0.5;
    	int rectifyY = (double)yCoordinate/(double)oriCount + 0.5;
    	//校准半径
    	int rectifyR1 = 0;
    	for (int x1 = xLeft ; x1 < xRight; x1++ ){
    		CvScalar s = cvGet2D(pImg8uOri, rectifyY, x1);
    		if (s.val[0] < 128) {
    			rectifyR1 = rectifyX - x1;
    			break;
    		}
    	}
    	int rectifyR2 = 0;
    	for (int x1 = xRight ; x1 > xLeft; x1-- ){
    		CvScalar s = cvGet2D(pImg8uOri, rectifyY, x1);
    		if (s.val[0] < 128) {
    			rectifyR2 = x1 - rectifyX;
    			break;
    		}
    	}
    	int rectifyR3 = 0;
    	for (int y1 = yLeft ; y1 < yRight; y1++ ){
    		CvScalar s = cvGet2D(pImg8uOri, y1, rectifyX);
    		if (s.val[0] < 128) {
    			rectifyR3 = rectifyY - y1;
    			break;
    		}
    	}
    	int rectifyR4 = 0;
    	for (int y1 = yRight ; y1 > yLeft; y1-- ){
    		CvScalar s = cvGet2D(pImg8uOri, y1, rectifyX);
    		if (s.val[0] < 128) {
    			rectifyR4 = y1 - rectifyY;
    			break;
    		}
    	}
    	int rectifyR = (double)(rectifyR1 + rectifyR2 + rectifyR3 + rectifyR4)/(double)4 + 0.5;
    	//cvCircle(pImg8uOri,cvPoint(cvRound(p[0]),cvRound(p[1])),cvRound(p[2]),CV_RGB(0,255,0),1,CV_AA,0);
    	//cvCircle(pImg8uOri,cvPoint(cvRound(p[0]),cvRound(p[1])),1,CV_RGB(155,50,255),1,CV_AA,0);
    		
    	int p2 = rectifyR;
    	if(p2 >= 18 || p2 <= 12){
    		p2 = 15;
    	}
    	circleCount = circleCount + 1;
    	if(maxD == 0){
    		maxD = D;
    		maxPx = rectifyX;
    		maxPy = rectifyY;
    		maxR = p2;
    		px = maxPx;
    		py = maxPy;
    		pr = maxR;
    	}
    	if(circleCount > 1){
    		/如果有多个圆符合条件,则选出圆度最大的圆,也就是最圆的圆
    		if(maxD > D){
    			//原来识别出的圆更圆
    			px = maxPx;
    			py = maxPy;
    			pr = maxR;
    		}else{
    			//新圆更圆
    			maxPx = rectifyX;
    			maxPy = rectifyY;
    			maxR = p2;
    			px = maxPx;
    			py = maxPy;
    			pr = maxR;
    		}
    	}
    	return cvPoint(px,py);
    }

    bool  Card::isFilled(IplImage *pImg8u , int x ,int y , int r)
    {
    	int xRight = x;
    	int xLeft = x;
    	int yTop = y;
    	int yBottom = y;
    	for (int x1 = x ; x1<=x+r;x1++ )
    	{
    		CvScalar s = cvGet2D(pImg8u, y, x1);
    		if (s.val[0] < 128) {
    			xRight = x1;
    		} else {
    			break ;
    		}
    	}
    	for (int y1=y ; y1<=y+r;y1++ )
    	{
    		CvScalar s = cvGet2D(pImg8u, y1, x);
    		if (s.val[0] < 128){
    			yBottom =y1;
    		} else {
    			break;
    		}
    	}
    	for (int x1 = x ; x1>=x-r;x1-- )
    	{
    		CvScalar s = cvGet2D(pImg8u, y, x1);
    		if (s.val[0] < 128) {
    			xLeft = x1;
    		} else {
    			break ;
    		}
    	}
    	for (int y1=y ; y1>=y-r;y1-- )
    	{
    		CvScalar s = cvGet2D(pImg8u, y1, x);
    		if (s.val[0] < 128){
    			yTop =y1;
    		} else {
    			break;
    		}
    	}
    
    	//边缘检测后的圆可能并不十分完美,houghCircle可能不能十分准确的找出圆心
    	//参数被从10调为7
    	if ((xRight-x)<7 || (x-xLeft)<7 || (yBottom-y)<7 || (y-yTop)<7) {
    		return false;
    	}else{
    		//圆点周围11*11的范围,点的覆盖率需大于95%
    		if((x - 5)<=0 || (y - 5)<=0 || (x + 5)>=400 || (y + 5)>=400){
    			return false;
    		}
    		int SqCount = 0;
    		for(int m1=x-5; m1<=x+5; m1++){
    			for(int m2=y-5; m2<=y+5; m2++){
    				CvScalar s3 = cvGet2D(pImg8u, m2, m1);
    				if (s3.val[0] < 128){
    					SqCount = SqCount + 1;
    				}
    			}
    		}
    		if(SqCount >= 115){
    			return true;
    		}else{
    			return false;
    		}
    	}
    
    }



    圆度公式的那块,算法还有点问题,不完善。

    主要问题是,我简单的把边缘检测后的黑点累加和认为是周长,原图片的黑点累加和认为是面积了。

    但是如果,所截取的部分并不是完整的时候,周长的计算就会有问题。

    以后有空再进行完善~



    展开全文
  • 我们从客户历史登入成功这些输入特性中利用算法来评估出一个标准范围,来判断以后输入是否存在非本人之类风险情况! 我们可以将用户特性都看作如上图坐标上一个点,输入特性不同,点位置也就不同,以...

    ⽤户输⼊特性评估

    算法推理

    传过来的用户输入特性,是用户输入用户名,密码,验证码各自所用的时间,
    我们从客户历史登入成功的这些输入特性中利用算法来评估出一个标准范围,来判断以后的输入是否存在非本人之类的风险情况!

    在这里插入图片描述
    我们可以将用户的特性都看作如上图坐标上的一个点,输入特性不同,点的位置也就不同,以一个圆为标准,圆内为正常圆外为异常!(之所以用圆而不用正方形之类的是因为圆从圆心无论到哪个方向的边都是同距离的)

    问题来了:一,如何确定圆心

    用平均输入时长,历史输入的平均值,中值点

    问题二,如何确定半径

    1,先计算所有已知点两两间距
    如果有N 个点 会有几个间距值为采样点? 为 n(n-1)/ 2 个 符合等差数列
    2,对获取到的样本点距离进行排序
    3,我们取排序后序列的2/3 作为半径(因为要拿的是客户的输入习惯,所以拿的要大于1/2)也可以用0.618黄金分割点

    问题三,我们如何计算当前用户输入与中心的距离

    在这里插入图片描述

    算法捋好了,那就进行代码实现环节喽

    package com.baizhi.evaluate.impl;
    
    import com.baizhi.enties.EvaluateData;
    import com.baizhi.enties.EvaluateReport;
    import com.baizhi.enties.HistoryData;
    import com.baizhi.enties.RiskFactor;
    import com.baizhi.evaluate.Evaluate;
    import com.baizhi.evaluate.EvaluateChain;
    
    import java.util.ArrayList;
    import java.util.List;
    import java.util.stream.Collectors;
    
    public class InputFeatureEvaluate extends Evaluate {
        public InputFeatureEvaluate() {
            super(RiskFactor.INPUTFEATURE);
        }
    
        @Override
        public void eval(EvaluateData evaluateData, HistoryData historyData, EvaluateReport evaluateReport,
                         EvaluateChain evaluateChain) {
            evaluateReport.signReport(getRiskFactor(),
                    doInputFeature(evaluateData.getInputFeatures(),historyData.getLatestInputFeatures()));
            //往后调
            evaluateChain.daChain(evaluateData,historyData,evaluateReport);
        }
    
        /**
         * 1.计算圆心中点
         * 2.计算两两特征距离
         * 3.对距离进行排序(升序),取2/3处作为评估距离阈值 - threshold
         * 4.计算当前输入的特征距离中心点距离
         */
        public boolean doInputFeature(Double[] inputFeatures, List<Double[]> latestInputFeatures){
            //如果没有历史证明第一次登,如果历史少于两个则没必要评估和也没法评估
            if (latestInputFeatures==null | latestInputFeatures.size()<2) return false;
            //圆中心坐标
            Double[] doubles = centrePoint(latestInputFeatures);
            //圆半径
            double radius = radius(latestInputFeatures);
            //输入特性到圆心的距离
            double distance = distance(inputFeatures, doubles);
            return  distance>radius;
        }
    
        //计算圆中心
        public Double[] centrePoint(List<Double[]> latestInputFeatures){
            double a=0.0;
            double b=0.0;
            double c=0.0;
            for (Double[] latestInputFeature : latestInputFeatures) {
                a+=latestInputFeature[0];
                b+=latestInputFeature[1];
                c+=latestInputFeature[2];
            }
            int size = latestInputFeatures.size();
            Double[] d={a/size,b/size,c/size};
            return d;
        }
        //计算圆半径
        public double radius(List<Double[]> latestInputFeatures){
            List<Double> list=new ArrayList<>();
            for (int i=0 ;i<latestInputFeatures.size();i++){
                Double[] inputFeatures = latestInputFeatures.get(i);
                for (int a=i+1;a<latestInputFeatures.size();a++){
                    double distance = distance(inputFeatures,latestInputFeatures.get(a));
                    list.add(distance);
                }
            }
            //对集合进行排序然后取2/3 处作为半径
            int c=  latestInputFeatures.size();
           int b= c*(c-1)/3;
            Double aDouble = list.stream().sorted().collect(Collectors.toList()).get(b);
            return aDouble;
        }
    
        //计算 输入特性到圆点的距离
        public double distance(Double[] inputFeatures,Double[] doubles){
            //使用的是欧式距离公式
            double a=0.0;
            for(int i=0;i<inputFeatures.length;i++){
                a+=(inputFeatures[i]-doubles[i])*(inputFeatures[i]-doubles[i]);
            }
            //返回开平方的结果
            return Math.sqrt(a);
        }
    
        //测试下
        public static void main(String[] args) {
            InputFeatureEvaluate inputFeatureEvaluate = new InputFeatureEvaluate();
            ArrayList<Double[]> latestInputFeatures = new ArrayList<>();
            latestInputFeatures.add(new Double[]{1000.0,1100.0,1800.0});
            latestInputFeatures.add(new Double[]{1100.0,1120.0,1750.0});
            latestInputFeatures.add(new Double[]{950.0,1250.0,2000.0});
            latestInputFeatures.add(new Double[]{1200.0,1050.0,1900.0});
            latestInputFeatures.add(new Double[]{1400.0,800.0,2500.0});
    
            System.out.println(inputFeatureEvaluate.doInputFeature(new Double[]{100.0, 1000.0, 1750.0}, latestInputFeatures));
        }
    
    }
    
    
    展开全文
  • 计算几何算法源码

    热门讨论 2013-07-29 19:27:02
    6. 判断圆是否在多边形内 7. 求矢量夹角余弦 8. 求线段之间夹角 9. 判断线段是否相交 10.判断线段是否相交但不交在端点处 11.求线段所在直线方程 12.求直线斜率 13.求直线倾斜角 14.求点关于某直线对称点 ...
  • 计算几何

    热门讨论 2012-08-06 21:49:17
    6. 判断圆是否在多边形内 5 7. 求矢量夹角余弦 5 8. 求线段之间夹角 5 9. 判断线段是否相交 6 10.判断线段是否相交但不交在端点处 6 11.求线段所在直线方程 6 12.求直线斜率 7 13.求直线倾斜角 7 14...
  • 空间几何计算

    2014-03-18 14:11:08
    6. 判断圆是否在多边形内 5 7. 求矢量夹角余弦 5 8. 求线段之间夹角 5 9. 判断线段是否相交 6 10.判断线段是否相交但不交在端点处 6 11.求线段所在直线方程 6 12.求直线斜率 7 13.求直线倾斜角 7 14...
  • 1.16.7 pku_3335_判断多边形是否存在 67 1.16.8 pku_2600_二分+圆的参数方程 74 1.16.9 pku_1151_矩形相交面积 76 1.16.10 pku_1118_共线最多个数 78 1.16.11 pku2826_线段围成区域可储水量 80 1.16....
  • LINGO软件学习

    2009-08-08 22:36:50
    #eq#是逻辑运算符,用来判断是否“相等”,可参考§4. &1可看作派生集第1个原始父集索引,它取遍该原始父集所有成员;&2可看作派生集第2 个原始父集索引,它取遍该原始父集所有成员;&3,&4,……,...
  • 最后如果数字存在的话,令走后面的index减去最前面的index然后+1即可。在进行有序数组的元素查找,可以先尝试一下二分查找 面试题39:二叉树的深度:利用递归实现。如果一棵树只有一个结点,那么它的深度为1。递归的...
  • c语言经典案例

    2014-10-30 08:06:57
    实例104 判断一个数是否存在数组中 135 实例105 求二维数组对角线之和 136 实例106 模拟比赛打分 137 实例107 矩阵转置 139 实例108 设计魔方阵 141 实例109 字符升序排列 142 实例110 在指定位置插入字符 144 ...
  • 因此这里我增加了一个回收功能//首先判断栈中是否存在回收对象,若存在,则直接复用,若不存在,则创建一个新对象 private RainDrop obtainRainDrop(){  if (mRecycler.isEmpty()){  return new RainDrop...
  • 实例003 打开已存在的工程 实例004 怎样查找工程中的信息 实例005 怎样在添加对话框资源时创建对话框类 实例006 在工作区中管理多个工程 实例007 创建MFC ActiveX工程 实例008 创建ATL工程 实例009 创建...
  • 实例003 打开已存在的工程 实例004 怎样查找工程中的信息 实例005 怎样在添加对话框资源时创建对话框类 实例006 在工作区中管理多个工程 实例007 创建MFC ActiveX工程 实例008 创建ATL工程 实例009 创建...
  • 语句if(x == 3)首先判断x是否为3,若相等条件表达式值为ture,否则为false。 2-15 什么叫做作用域?什么叫做局部变量?什么叫做全局变量,如何使用全局变量? 解: 作用域是一个标识符在程序正文中有效...
  • JAVA 正则表达式

    热门讨论 2010-01-15 11:16:37
    众所周知,在程序开发中,难免会遇到需要匹配、查找、替换、判断字符串情况发生,而这些情况有时 又比较复杂,如果用纯编码方式解决,往往会浪费程序员时间及精力。因此,学习及使用正则表达式, 便成了解决这...
  • C#编程经验技巧宝典

    热门讨论 2008-06-01 08:59:33
    值 52 <br>0069 求最大公约数 52 <br>0070 求最小公倍数 53 <br>0071 判断素数算法 53 <br>0072 如何判断一个数是否是完数 54 <br>0073 歌德巴赫猜想算法 54 <br>0074 八皇后...
  • 易语言模块大全

    2013-12-05 15:48:22
    判断进程是否存在的模块.ec 判断数据库.ec 判断字符模块.ec 配置文件操作.ec 配置文件操作模块3.0.ec 配置文件扩充操作模块.ec 皮肤_易语言皮肤模块.ec 频谱.ec 屏蔽win键.ec 屏蔽超文本浏览框右键菜单2.2....
  • 判断进程是否存在的模块.ec 到文本.ec 办公组件密码管理模块.ec 功能集一模块 1.0.ec 功 能集一模块 1[1].0.ec 功能集一模块.ec 功能集一模块_吴涛.ec 加入好友.ec 加入自身.ec 加 密.ec 加密文件头模块.ec 加密解密...
  • 易语言模块914个

    2018-03-12 20:00:21
    判断进程是否存在的模块.ec 到文本.ec 办公组件密码管理模块.ec 功能集一模块 1.0.ec 功能集一模块.ec 加入好友.ec 加密.ec 加密解密文本.ec 加密解密文本1.0.ec 加密配置文件操作模块.ec 加强执行1.0.ec...
  • Proteus仿真—40个单片机初学程序.

    热门讨论 2009-04-13 13:00:56
    作为单片机指令执行时间是很短,数量大微秒级,因此,我们要求闪烁时间间隔为0.2秒,相对于微秒来说,相差太大,所以我们在执行某一指令时,插入延时程序,来达到我们要求,但这样延时程序是如何设计呢...
  • 1345个易语言模块

    2012-01-27 19:41:59
    判断进程是否存在的模块.ec 到文本.ec 办公组件密码管理模块.ec 功能集一模块 1.0.ec 功 能集一模块 1[1].0.ec 功能集一模块.ec 功能集一模块_吴涛.ec 加入好友.ec 加入自身.ec 加 密.ec 加密文件头模块.ec 加密解密...
  • 1350多个精品易语言模块提供下载

    热门讨论 2011-06-06 17:51:09
    判断进程是否存在的模块.ec 到文本.ec 办公组件密码管理模块.ec 功能集一模块 1.0.ec 功 能集一模块 1[1].0.ec 功能集一模块.ec 功能集一模块_吴涛.ec 加入好友.ec 加入自身.ec 加 密.ec 加密文件头模块.ec 加密解密...
  • 判断进程是否存在的模块.ec 到文本.ec 办公组件密码管理模块.ec 功能集一模块 1.0.ec 加入好友.ec 加密.ec 加密解密文本.ec 加密配置文件操作模块.ec 加强执行1.0.ec 加解密文本1.1.ec 加载进度条.ec 加载进度条v2.0...

空空如也

空空如也

1 2
收藏数 24
精华内容 9
关键字:

判断圆是否存在的公式