精华内容
下载资源
问答
  • 四边形最小外接矩形

    千次阅读 2019-02-26 09:09:58
    已知凸四边形的四条边及对角线长度,求具有最小面积的外接矩形的面积。 思路: 1 最初上来,没好的想法只能遍历,绕某个点转360度,求解析解; 2 发现不对,再遍历四个点; 3 绕重心旋转,遍历求最优近似解; 4...

    问题简单描述:

    已知凸四边形的四条边及对角线长度,求具有最小面积的外接矩形的面积。

    思路:

    1 最初上来,没好的想法只能遍历,绕某个点转360度,求解析解;

    2 发现不对,再遍历四个点;

    3 绕重心旋转,遍历求最优近似解;

    4 发现opencv有对应的函数minAreaRect,看源码或者调用

    5 发现有证明,某条边必在矩形上,化为只需求四次最优解;对每个需分析两个底角的钝角锐角情况,有三种情况。

    最终实现:

    第四种。解析实现。

    可推广到任意多个点的最小外接矩形。

    展开全文
  • python opencv minAreaRect 生成最小外接矩形

    万次阅读 多人点赞 2017-08-03 11:05:33
    1、方法: 使用python opencv返回点集cnt的最小外接矩形,所用...画一个任意四边形(任意多边形都可以)的最小外接矩形,那么点集cnt 存放的就是该四边形的4个顶点坐标(点集里面有4个点) cnt = np.array([[x1,y...

    方法

    使用python opencv返回点集cnt的最小外接矩形,所用函数为 cv2.minAreaRect(cnt) ,cnt是点集数组或向量(里面存放的是点的坐标),并且这个点集中的元素不定个数。

    举例说明

    画一个任意四边形(任意多边形都可以)的最小外接矩形,那么点集 cnt 存放的就是该四边形的4个顶点坐标(点集里面有4个点)

    cnt = np.array([[x1,y1],[x2,y2],[x3,y3],[x4,y4]]) # 必须是array数组的形式
    rect = cv2.minAreaRect(cnt) # 得到最小外接矩形的(中心(x,y), (宽,高), 旋转角度)
    box = cv2.cv.BoxPoints(rect) # 获取最小外接矩形的4个顶点坐标(ps: cv2.boxPoints(rect) for OpenCV 3.x)
    box = np.int0(box)
    # 画出来
    cv2.drawContours(img, [box], 0, (255, 0, 0), 1)
    cv2.imwrite('contours.png', img)

    函数 cv2.minAreaRect() 返回一个Box2D结构rect:(最小外接矩形的中心(x,y),(宽度,高度),旋转角度),但是要绘制这个矩形,我们需要矩形的4个顶点坐标box, 通过函数 cv2.cv.BoxPoints() 获得,返回形式[ [x0,y0], [x1,y1], [x2,y2], [x3,y3] ]。得到的最小外接矩形的4个顶点顺序、中心坐标、宽度、高度、旋转角度(是度数形式,不是弧度数)的对应关系如下:

    注意:

    • 旋转角度θ是水平轴(x轴)逆时针旋转,直到碰到矩形的第一条边停住,此时该边与水平轴的夹角。并且这个边的边长是width,另一条边边长是height。也就是说,在这里,width与height不是按照长短来定义的。
    • 在opencv中,坐标系原点在左上角,相对于x轴,逆时针旋转角度为负,顺时针旋转角度为正。所以,θ∈(-90度,0]。

     

     

     

    展开全文
  • python opencv minAreaRect 生成最小外接矩形的方法使用python opencv返回点集...举例说明:画一个任意四边形(任意多边形都可以)的最小外接矩形,那么点集cnt 存放的就是该四边形的4个顶点坐标(点集里面有4个点)cnt ...

    python opencv minAreaRect 生成最小外接矩形的方法

    使用python opencv返回点集cnt的最小外接矩形,所用函数为 cv2.minAreaRect(cnt) ,cnt是点集数组或向量(里面存放的是点的坐标),并且这个点集不定个数。

    举例说明:画一个任意四边形(任意多边形都可以)的最小外接矩形,那么点集 cnt 存放的就是该四边形的4个顶点坐标(点集里面有4个点)

    cnt = np.array([[x1,y1],[x2,y2],[x3,y3],[x4,y4]]) # 必须是array数组的形式

    rect = cv2.minAreaRect(cnt) # 得到最小外接矩形的(中心(x,y), (宽,高), 旋转角度)

    box = cv2.cv.BoxPoints(rect) # cv2.boxPoints(rect) for OpenCV 3.x 获取最小外接矩形的4个顶点坐标

    box = np.int0(box)

    函数 cv2.minAreaRect() 返回一个Box2D结构rect:(最小外接矩形的中心(x,y),(宽度,高度),旋转角度),但是要绘制这个矩形,我们需要矩形的4个顶点坐标box, 通过函数 cv2.cv.BoxPoints() 获得,返回形式[ [x0,y0], [x1,y1], [x2,y2], [x3,y3] ]。得到的最小外接矩形的4个顶点顺序、中心坐标、宽度、高度、旋转角度(是度数形式,不是弧度数)的对应关系如下:

    注意:

    旋转角度θ是水平轴(x轴)逆时针旋转,与碰到的矩形的第一条边的夹角。并且这个边的边长是width,另一条边边长是height。也就是说,在这里,width与height不是按照长短来定义的。

    在opencv中,坐标系原点在左上角,相对于x轴,逆时针旋转角度为负,顺时针旋转角度为正。所以,θ∈(-90度,0]。

    以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

    时间: 2019-06-29

    本文实例为大家分享了Android九宫格图片展示的具体代码,供大家参考,具体内容如下 一.基本原理 Mat img= imread(image): Rect rect(50,20, 200, 50); Mat ROI = img(rect); imshow("ROI_WIN",ROI); - 其中:Rect的函数定义为: Rect(_Tp _x, _Tp _y, _Tp _width, _Tp _height); _Tp _x:表示矩形左上角顶点的x坐标: _Tp _y:表示矩形左上角

    Opencv中求点集的最小外结矩使用方法minAreaRect,求点集的最小外接圆使用方法minEnclosingCircle. minAreaRect方法原型: RotatedRect minAreaRect( InputArray points ); 输入参数points是所要求最小外结矩的点集数组或向量: minEnclosingCircle方法原型: void minEnclosingCircle( InputArray points, CV_OUT Point2f& center, C

    这段时间一直在用opencv搞图像处理的问题,发现虽然可调用的函数多,但是直接找相应代码还是很困难,就行寻找连通域,并在连通域外侧加框,对于习惯使用Mat矩形操作的我,真心感觉代码少之又少,为防止以后自己还会用到,特在此记录一下. 要对下面的图像进行字符的边缘检测. 程序中具体的步骤为: (1)灰度化.二值化 (2)图像膨胀 (3)检测膨胀图像的边缘并叫外矩形框 实现代码如下: #include "stdafx.h" #include "stdio.h" #incl

    前两篇博文分别介绍了图像的边缘检测和轮廓检测,本文接着介绍图像的轮廓检测和轮廓外接矩形: 一.代码部分: // extract_contours.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include #include using namespace cv; using namespace std; int _tmain(int argc, _TCHAR* argv[]) { /

    本文实例为大家分享了OpenCV鼠标绘制截取矩形区域图像的具体代码,供大家参考,具体内容如下 在opencv中利用鼠标绘制矩形,代码如下: #include #include #include #pragma comment( lib, "cv.lib" ) #pragma comment( lib, "cxcore.lib" ) #pragma comment( lib,

    有时候需要对有角度的矩形框内图像从原图片中分割出来.这里的程序思想是,先将图片进行矩形角度的旋转,使有角度的矩形处于水平状态后,根据原来坐标分割图片. 参考:python opencv实现旋转矩形框裁减功能 修改原来的程序: 1.旋转函数的输入仅为矩形的四点坐标 2.角度由公式计算出来 3.矩形四点pt1,pt2,pt3,pt4由txt文件读入 4.在旋转程序中还处理了顺时针和逆时针及出现矩形框翻转的问题. 代码: # -*- coding:utf-8 -*- import cv2 from m

    本文实例为大家分享了Opencv实现最小外接矩形和圆的具体代码,供大家参考,具体内容如下 步骤:将一幅图像先转灰度,再canny边缘检测得到二值化边缘图像,再寻找轮廓,轮廓是由一系列点构成的,要想获得轮廓的最小外接矩形,首先需要得到轮廓的近似多边形,用道格拉斯-普克抽稀(DP)算法,道格拉斯-普克抽稀算法,是将曲线近似表示为一系列点,并减少点的数量的一种算法. 该算法实现抽稀的过程是: 1)对曲线的首末点虚连一条直线,求曲线上所有点与直线的距离,并找出最大距离值dmax,用dmax与事先给定的阈

    本文实例为大家分享了OpenCV选择图像中矩形区域并保存的具体代码,供大家参考,具体内容如下 根据中的example4.1改写: // An example program in which the // user can draw boxes on the screen. // //#include //#include #include "opencv2/imgproc/imgproc

    如下所示: def draw_circle(event,x,y,flags,param): global ix,iy,drawing,mode,start_x,start_y if event == cv2.EVENT_LBUTTONDOWN: if drawing == False: start_x, start_y = x,y ix,iy = x,y drawing = True elif drawing == True: cv2.line(img,(ix,iy),(x,y),(0,255,

    本文实例为大家分享了python opencv实现旋转矩形框裁减的具体代码,供大家参考,具体内容如下 经常遇见旋转矩形框的裁减问题,那么思路是,将矩形框旋转正然后再裁减 # -*- coding:gb2312 -*- import cv2 from math import * import numpy as np import time def rotateImage(img,degree,pt1,pt2,pt3,pt4): height,width=img.shape[:2] heightNe

    先说明下,我这是对某个目录下的图片名称进行操作,该目录下的图片名称为1.jpg,2.jpg.....这样类似的图片名. 1.旋转 # -*-coding:utf-8-*- from PIL import Image def rotateimg(inputimg,outimg): im = Image.open(inputimg) # 图片的宽度和高度 img_size = im.size print("图片宽度和高度分别是{}".format(img_size)) # 旋转图片 # 左

    假设我们有一幅图像,图像中的文本被旋转了一个未知的角度.为了对文字进行角度的校正,我们需要完成如下几个步骤: 1.检测出图中的文本范围 2.计算出文本被旋转的角度 3.将图像旋转特定的角度 第一步.读取图像,并做二值化处理 #读取图像,做二值化处理 img = cv.imread('img/imageTextR.png') gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY) cv.imshow('gray', gray) #像素取反,变成白字黑底 # gray

    0x01 OpenCV安装 通过命令pip install opencv-python 安装 pip install opencv-python 0x02  示例 import cv2 cap = cv2.VideoCapture(0) #打开摄像头 while(1): # get a frame ret, frame = cap.read() # show a frame cv2.imshow("capture", frame) #生成摄像头窗口 if cv2.waitKey(1)

    如下所示: def mat_inter(box1,box2): # 判断两个矩形是否相交 # box=(xA,yA,xB,yB) x01, y01, x02, y02 = box1 x11, y11, x12, y12 = box2 lx = abs((x01 + x02) / 2 - (x11 + x12) / 2) ly = abs((y01 + y02) / 2 - (y11 + y12) / 2) sax = abs(x01 - x02) sbx = abs(x11 - x12) say

    我就废话不多说了,直接上代码吧! import cv2 from math import fabs, sin, cos, radians import numpy as np from scipy.stats import mode def get_img_rot_broa(img, degree=45, filled_color=-1): """ Desciption: Get img rotated a certain degree, and use some color

    本文实例为大家分享了python openCV获取人脸部分并存储的具体代码,供大家参考,具体内容如下 #-*- coding:utf-8 -*- import cv2 import os import time import base64 import numpy as np save_path = 'E:\\opencv\\2018-04-24OpenCv\\RAR\\savetest' faceCascade = cv2.CascadeClassifier( './haarcascade_f

    本文实例讲述了Python基于OpenCV库Adaboost实现人脸识别功能.分享给大家供大家参考,具体如下: 以前用Matlab写神经网络的面部眼镜识别算法,研究算法逻辑,采集大量训练数据,迭代,计算各感知器的系数...相当之麻烦~而现在运用调用pythonOpenCV库Adaboost算法,无需知道算法逻辑,无需进行模型训练,人脸识别变得相当之简单了. 需要用到的库是opencv(open source computer vision),下载安装方式如下: 使用pip install num

    展开全文
  • 检测四边形轮廓以及角点 */ /*晚上调好模板匹配以及透视变换,再试试OCR库 */ #pragma warning(disable:4996) // #include <opencv.hpp> #include <opencv2/video.hpp...

    这里写图片描述

    /*
    工程在69那个例程文件目录
    
    检测四边形轮廓以及角点
    */
    
    
    /*晚上调好模板匹配以及透视变换,再试试OCR库
    
    
    */
    
    
    #pragma warning(disable:4996)
    
    
    
    
    //
    
    #include <opencv.hpp>  
    #include <opencv2/video.hpp>
    #include <opencv2/imgPRoc//imgproc.hpp>
    #include <opencv2/ml/ml.hpp>
    #include <opencv2/imgproc/imgproc.hpp>  
    #include <opencv2/highgui/highgui.hpp>  
    
    #include <iostream>  
    #include<time.h>
    #include<math.h>
    #include <set>
    
    
    using namespace cv;
    using namespace std;
    
    
    
    //-----------------------------------【命名空间声明部分】--------------------------------------
    //          描述:包含程序所使用的命名空间
    //-----------------------------------------------------------------------------------------------
    using namespace cv;
    using namespace std;
    
    
    RNG rng(12345);
    
    float getDistance(CvPoint pointO, CvPoint pointA);
    float getAngle(CvPoint pointM, CvPoint pointL, CvPoint pointR);
    
    float getDist_P2L(CvPoint pointP, CvPoint pointA, CvPoint pointB);
    int list_connor(int i1, int i2, int i3);
    
    
    
    
    //-----------------------------------【全局函数声明部分】--------------------------------------
    //   描述:全局函数的声明
    //-----------------------------------------------------------------------------------------------
    static void ShowHelpText();
    
    
    //-----------------------------------【main( )函数】--------------------------------------------
    //   描述:控制台应用程序的入口函数,我们的程序从这里开始执行
    //-----------------------------------------------------------------------------------------------
    
    int main()
    {
        int iiii = 1000;
        int n = 1;//保存图片名称末尾
    
        int geshu = 0;
        Mat frame;
        Mat srcImage = Mat::zeros(600, 800, CV_8UC3);
        //【0】显示欢迎和帮助文字
        ShowHelpText();
    
        char strangerName[2000];//截取的四边形矩形图片名字
        //定义一些参数3
        Mat threshold_output;
        vector<vector<Point>> contours;
        vector<Vec4i> hierarchy;
    
    
    
        //【1】从摄像头读入视频
        VideoCapture capture(1);  //该参数为0,则打开计算机自带摄像头,如果为1则打开外置USB摄像头
    
    
        //capture.set(CAP_PROP_FRAME_WIDTH, 1920.0);//设置摄像头采集图像分辨率
       //  capture.set(CAP_PROP_FRAME_HEIGHT, 1080.0);
    
    
    
        while (1)
        {
    
    
            iiii++;
    
    
    
    
    
            //隔一段时间保存一张图片
            if (iiii >= 500)//通过改变i后面的值来刷新图片界面
            {
                clock_t start = clock();
                iiii = 0;
                capture >> frame;// //读取当前帧,capture >> frame与capture.read(frame)功能一样,
                if (frame.empty())
                {
                    return 0;
                }
                char* cstr = new char[120];
    
    
    
                //Mat srcImage0 = imread("10.jpg", 0);
                resize(frame, srcImage, srcImage.size());
            //  srcImage = srcImage > 200;//二值化
    
    
    
                //灰度化
                cvtColor(srcImage, srcImage, CV_BGR2GRAY);//灰度化
    
                //二值化
                  threshold(srcImage, srcImage, 200, 255, CV_THRESH_BINARY | CV_THRESH_OTSU);
    
    
    
    
    
    
    
                  namedWindow("原图", 1);
                imshow("原图", srcImage);
                waitKey(30);
                //getStructuringElement函数会返回指定形状和尺寸的结构元素
                Mat element = getStructuringElement(MORPH_RECT, Size(3, 3));
                //morphologyEx(srcImage, srcImage, MORPH_CLOSE, element);//闭运算滤波
                vector<vector<Point>> contours, RectContours;//轮廓,为点向量,
                findContours(srcImage, contours, CV_RETR_LIST, CV_CHAIN_APPROX_NONE);//找轮廓
                vector<vector<Point>> hull(contours.size());//用于存放凸包
                Mat drawing(srcImage.size(), CV_8UC3, cv::Scalar(0));
                int i = 0;
                vector<float> length(contours.size());//用于保存每个轮廓的长度
                vector<float> Area_contours(contours.size()), Area_hull(contours.size()), Rectangularity(contours.size()), circularity(contours.size());
                for (i = 0; i < contours.size(); i++)
                {//把所有的轮廓画出来
                    Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
                    length[i] = arcLength(contours[i], true);//轮廓的长度
                    if (length[i] >200 && length[i] <2000)
                    {//通过长度匹配滤除小轮廓
                        convexHull(Mat(contours[i]), hull[i], false);//把凸包找出来,寻找凸包函数
                        Area_contours[i] = contourArea(contours[i]);   //轮廓面积
                        Area_hull[i] = contourArea(hull[i]);           //凸包面积
                        Rectangularity[i] = Area_contours[i] / Area_hull[i]; //矩形度
                        circularity[i] = (4 * 3.1415*Area_contours[i]) / (length[i] * length[i]);//圆形度
                        //drawContours(drawing, contours, i, color, 1);//得到方框
    
                        if (Rectangularity[i]>0.8&&circularity[i]<0.95)
                        {//通过矩形度和圆形度滤除数字
                            //drawContours(drawing, contours, i, Scalar(255, 255, 255), 1);
                            RectContours.push_back(hull[i]);//把提取出来的方框导入到新的轮廓组
                            drawContours(drawing, hull, i, color, 1);//得到四边形
    
    
                        }
                    }
                }
                /**********************     自己添加的用于切割四边形     **************************************************************************************************************/
                /**********************     自己添加的     **************************************************************************************************************/
    
                // 多边形逼近轮廓 + 获取矩形和圆形边界框
                vector<vector<Point> > contours_poly(RectContours.size());
                vector<Rect> boundRect(RectContours.size()); //最小矩形
                vector<Point2f>center(RectContours.size()); //圆心
                vector<float>radius(RectContours.size()); //半径
    
                //一个循环,遍历所有部分,进行本程序最核心的操作
                for (unsigned int i = 0; i < RectContours.size(); i++)
                {
                    approxPolyDP(RectContours[i], contours_poly[i], 3, true);//用指定精度逼近多边形曲线 
                    boundRect[i] = boundingRect(Mat(contours_poly[i]));//计算点集的最外面(up-right)矩形边界
                    minEnclosingCircle(contours_poly[i], center[i], radius[i]);//对给定的 2D点集,寻找最小面积的包围圆形 
                }
    
                // 绘制多边形轮廓 + 包围的矩形框 + 圆形框
                Mat drawing1 = Mat::zeros(srcImage.size(), CV_8UC3);
    
                Mat image_cut[100];      //从img中按照rect进行切割,此时修改image_cut时image中对应部分也会修改,因此需要copy  
                Mat image_copy[100];   //clone函数创建新的图片 
                int geshu = 0;
                for (int unsigned i = 0; i < RectContours.size(); i++)
                {
    
                    Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));//随机设置颜色
                    //drawContours(drawing1, contours_poly, i, color, 1, 8, vector<Vec4i>(), 0, Point());//绘制轮廓
                    Point text_lb;//中点
    
    
                    //circle(drawing, center[i], (int)radius[i], color, 2, 8, 0);//绘制圆
                    //if (radius[i]<39 && radius[i]>20 && center[i].y>300 && center[i].x>200 && center[i].x<400)
                    //if (radius[i]<39 && radius[i]>20 && center[i].y>300 && center[i].x>350 && center[i].x<400)
                    //中间下面的点
                    //  if (radius[i]<39 && radius[i]>20 && center[i].y > 200 && center[i].x > 100 && center[i].x < 650)
                    //{
                    geshu++;
                    rectangle(drawing1, boundRect[i].tl(), boundRect[i].br(), color, 2, 8, 0);//绘制矩形
                    text_lb = Point((boundRect[i].tl().x + boundRect[i].br().x)*0.5, (boundRect[i].tl().y + boundRect[i].br().y)*0.5);
                    //putTextZH(drawing, "中点", center[i], Scalar(0, 0, 255), 10, "Arial");
                    int width = abs(boundRect[i].tl().x - boundRect[i].br().x);
                    int height = abs(boundRect[i].tl().y - boundRect[i].br().y);
    
    
    
                    Rect rect(boundRect[i].tl().x, boundRect[i].tl().y, width, height);   //创建一个Rect框,属于cv中的类,四个参数代表x,y,width,height  
    
                    image_cut[i] = Mat(srcImage, rect);      //从img中按照rect进行切割,此时修改image_cut时image中对应部分也会修改,因此需要copy  
                    image_copy[i] = image_cut[i].clone();   //clone函数创建新的图片  
                    sprintf_s(strangerName, "数字%d", geshu);
                    namedWindow(strangerName, 0);//参数为零,则可以自由拖动strangerName
                    imshow(strangerName, image_copy[i]);
    
    
    
    
                    //}
    
                }
    
                namedWindow("找到四边形外接矩形", 1);
                imshow("找到四边形外接矩形", drawing1);
                waitKey(30);
    
                ///****************************************************************************************************************************************/
                ///****************************************************************************************************************************************/
    
    
    
                float distance = 0, distanceMax = 0;
                Point connorPoint1, connorPoint2, connorPoint3, connorPoint4, point_add;
                vector<Point> connor4_add(3);  //先找到的三个角点
                int conP_i1, conP_i2, conP_i3, conP_i_add;
                int j = 0, flag = 0;
    
                Point  finally_contours[80][4];//轮廓,为点向量,新的轮廓
                for (j = 0; j < RectContours.size(); j++)  //四边形轮廓个数
                {
                    distance = 0;
                    distanceMax = 0;
                    for (i = 0; i < RectContours[j].size(); i++) //每个轮廓点的个数11到19点不等
                    {//找第一个角点
                        distance = getDistance(RectContours[j][i], RectContours[j][0]);
                        if (distance>distanceMax)
                        {
                            distanceMax = distance;
                            connorPoint1 = RectContours[j][i]; //第一个角点
                            conP_i1 = i;
                        }
                    }
                    distance = 0;
                    distanceMax = 0;
                    for (i = 0; i < RectContours[j].size(); i++)
                    {//找第二个角点
                        distance = getDistance(RectContours[j][i], connorPoint1);
                        if (distance>distanceMax)
                        {
                            distanceMax = distance;
                            connorPoint2 = RectContours[j][i]; //第二个角点
                            conP_i2 = i;
                        }
                    }
                    distance = 0;
                    distanceMax = 0;
                    for (i = 0; i < RectContours[j].size(); i++)
                    {//找第三个角点
                        distance = getDistance(RectContours[j][i], connorPoint1) + getDistance(RectContours[j][i], connorPoint2);
                        if (distance>distanceMax)
                        {
                            distanceMax = distance;
                            connorPoint3 = RectContours[j][i]; //第三个角点
                            conP_i3 = i;
                        }
                    }
                    flag = list_connor(conP_i1, conP_i2, conP_i3);//对三个角点由大到小排序
                    switch (flag)
                    {//对三个角点排序
                    case 0:break;
                    case 123:break;
                    case 132:point_add = connorPoint2; connorPoint2 = connorPoint3; connorPoint3 = point_add; break;//2,3交换
                    case 213:point_add = connorPoint1; connorPoint1 = connorPoint2; connorPoint2 = point_add; break;//1,2交换
                    case 231:point_add = connorPoint1; connorPoint1 = connorPoint2; connorPoint2 = point_add;
                        point_add = connorPoint2; connorPoint2 = connorPoint3; connorPoint3 = point_add; break;//1,2交换+2,3交换
                    case 321:point_add = connorPoint3; connorPoint3 = connorPoint1; connorPoint1 = point_add; break;//1,3交换
                    case 312:point_add = connorPoint3; connorPoint3 = connorPoint1; connorPoint1 = point_add;
                        point_add = connorPoint2; connorPoint2 = connorPoint3; connorPoint3 = point_add; break;//1,3交换+2,3交换
                    }
                    switch (flag)
                    {//对三个角点排序
                    case 0:break;
                    case 123:break;
                    case 132:conP_i_add = conP_i2; conP_i2 = conP_i3; conP_i3 = conP_i_add; break;//2,3交换
                    case 213:conP_i_add = conP_i1; conP_i1 = conP_i2; conP_i2 = conP_i_add; break;//1,2交换
                    case 231:conP_i_add = conP_i1; conP_i1 = conP_i2; conP_i2 = conP_i_add;
                        conP_i_add = conP_i2; conP_i2 = conP_i3; conP_i3 = conP_i_add; break;//1,2交换+2,3交换
                    case 321:conP_i_add = conP_i3; conP_i3 = conP_i1; conP_i1 = conP_i_add; break;//1,3交换
                    case 312:conP_i_add = conP_i3; conP_i3 = conP_i1; conP_i1 = conP_i_add;
                        conP_i_add = conP_i2; conP_i2 = conP_i3; conP_i3 = conP_i_add; break;//1,3交换+2,3交换
                    }
                    distance = 0;
                    distanceMax = 0;
                    for (i = conP_i3; i < conP_i2; i++)
                    {//相隔两角点之间找到怀疑是4角点的点
                        distance = getDistance(RectContours[j][i], connorPoint3) + getDistance(RectContours[j][i], connorPoint2);
                        if (distance>distanceMax)
                        {
                            distanceMax = distance;
                            connor4_add[0] = RectContours[j][i];
                        }
                    }
                    distance = 0;
                    distanceMax = 0;
                    for (i = conP_i2; i < conP_i1; i++)
                    {//相隔两角点之间找到怀疑是4角点的点
                        distance = getDistance(RectContours[j][i], connorPoint1) + getDistance(RectContours[j][i], connorPoint2);
                        if (distance>distanceMax)
                        {
                            distanceMax = distance;
                            connor4_add[1] = RectContours[j][i];
                        }
                    }
                    distance = 0;
                    distanceMax = 0;
                    for (i = conP_i1; i < RectContours[j].size() + conP_i3; i++)
                    {//相隔两角点之间找到怀疑是4角点的点
                        if (i< RectContours[j].size())
                        {
                            distance = getDistance(RectContours[j][i], connorPoint1) + getDistance(RectContours[j][i], connorPoint3);
                            if (distance>distanceMax)
                            {
                                distanceMax = distance;
                                connor4_add[2] = RectContours[j][i];
                            }
                        }
                        else
                        {
                            distance = getDistance(RectContours[j][i - RectContours[j].size()], connorPoint1) + getDistance(RectContours[j][i - RectContours[j].size()], connorPoint3);
                            if (distance>distanceMax)
                            {
                                distanceMax = distance;
                                connor4_add[2] = RectContours[j][i - RectContours[j].size()];
                            }
                        }
                    }
                    if (getDist_P2L(connor4_add[0], connorPoint3, connorPoint2)>10)
                    {
                        connorPoint4 = connor4_add[0];
                    }
                    else if (getDist_P2L(connor4_add[1], connorPoint2, connorPoint1)>10)
                    {
                        connorPoint4 = connor4_add[1];
                    }
                    else if (getDist_P2L(connor4_add[2], connorPoint1, connorPoint3)>10)
                    {
                        connorPoint4 = connor4_add[2];
                    }
    
                    circle(drawing, connorPoint1, 3, Scalar(255, 255, 255), FILLED, LINE_AA);
                    circle(drawing, connorPoint2, 3, Scalar(255, 255, 255), FILLED, LINE_AA);
                    circle(drawing, connorPoint3, 3, Scalar(255, 255, 255), FILLED, LINE_AA);
                    circle(drawing, connorPoint4, 3, Scalar(255, 255, 255), FILLED, LINE_AA);
    
                    finally_contours[j][0] = connorPoint1;
                    finally_contours[j][1] = connorPoint2;
                    finally_contours[j][2] = connorPoint3;
                    finally_contours[j][3] = connorPoint4;
    
                    cout << "\n轮廓 " << j + 1 << "  的四个角点坐标分别为:\n" << finally_contours[j][0] << finally_contours[j][1] << finally_contours[j][2] << finally_contours[j][3] << endl;
    
                }
    
    
                namedWindow("轮廓", 1);
                imshow("轮廓", drawing);
    
                clock_t ends = clock();
    
                cout << "Running Time : " << (double)(ends - start) / CLOCKS_PER_SEC << endl;
    
    
            }
    
        }
    
        return 0;
    }
    
    
    
    
    float getDist_P2L(CvPoint pointP, CvPoint pointA, CvPoint pointB)
    {//点到直线的距离:P到AB的距离
        //求直线方程
        int A = 0, B = 0, C = 0;
        A = pointA.y - pointB.y;
        B = pointB.x - pointA.x;
        C = pointA.x*pointB.y - pointA.y*pointB.x;
        //代入点到直线距离公式
        float distance = 0;
        distance = ((float)abs(A*pointP.x + B*pointP.y + C)) / ((float)sqrtf(A*A + B*B));
        return distance;
    }
    
    
    //对角点进行排序,因为之前检测出的轮廓是带序号的
    int list_connor(int i1, int i2, int i3)
    {//排序
        int flag = 0;
        Point point_add;
        if (i1 >= i2&&i2 >= i3)
            flag = 123;
        else if (i1 >= i3&& i3 >= i2)
            flag = 132;
        else if (i2 >= i1&&i1 >= i3)
            flag = 213;
        else if (i2 >= i3&&i3 >= i1)
            flag = 231;
        else if (i3 >= i2&&i2 >= i1)
            flag = 321;
        else if (i3 >= i1&&i1 >= i2)
            flag = 312;
        return flag;
    }
    
    
    
    float getDistance(CvPoint pointO, CvPoint pointA)
    {//求两点之间距离
        float distance;
        distance = powf((pointO.x - pointA.x), 2) + powf((pointO.y - pointA.y), 2);
        distance = sqrtf(distance);
    
        return distance;
    }
    
    float getAngle(CvPoint pointM, CvPoint pointL, CvPoint pointR)
    {//求三点之间的夹角
        CvPoint L, R;
        float dist_L, dist_R, Theta;
        L.x = pointL.x - pointM.x;
        L.y = pointL.y - pointM.y;
        R.x = pointR.x - pointM.x;
        R.y = pointR.y - pointM.y;
        dist_L = getDistance(pointL, pointM);
        dist_R = getDistance(pointR, pointM);
        Theta = acos((L.x*R.x + L.y*R.y) / (dist_L*dist_R));
        return Theta;
    }
    
    
    
    
    
    //-----------------------------------【ShowHelpText( )函数】----------------------------------  
    //      描述:输出一些帮助信息  
    //----------------------------------------------------------------------------------------------  
    static void ShowHelpText()
    {
        //输出欢迎信息和OpenCV版本
        printf("\n\n\t\t\t检测四边形角点\n");
        printf("\n\n\t\t\t   当前使用的OpenCV版本为:" CV_VERSION);
        printf("\n\n  ----------------------------------------------------------------------------\n");
    
        //输出一些帮助信息  
        printf("\n\n\n\t毛哥好\n\n");
        printf("\n\n\t按键操作说明: \n\n"
            "\t\t键盘按键【ESC】- 退出程序\n\n"
            "\t\t毛哥2018/5/24\n\n");
    }
    
    
    
    展开全文
  • 使用python opencv返回点集cnt的最小...举例说明:画一个任意四边形(任意多边形都可以)的最小外接矩形,那么点集cnt 存放的就是该四边形的4个顶点坐标(点集里面有4个点)cnt = np.array([[x1,y1],[x2,y2],[x3,y3],[...
  • 最小外接矩形

    2019-09-03 16:51:46
    使用python opencv返回点集cnt的最小外接矩形,所用函数为 cv2.minAreaRect(cnt) ,cnt是点集数组或向量(里面存放的是点的...举例说明:画一个任意四边形(任意多边形都可以)的最小外接矩形,那么点集 cnt 存放...
  • 利用模板匹配后,基于模板旋转1度角度逼近匹配目标图像,计算出第一个符合的...计算出最小旋转角度,但是需要绘制出旋转外接四边形, minMaxLoc函数,寻找到最小值的左上角顶点坐标,记录为x1,y1; 如图所示,偏转后的
  • 举例说明:画一个任意四边形(任意多边形都可以)的最小外接矩形,那么点集 cnt 存放的就是该四边形的4个顶点坐标(点集里面有4个点) cnt = np.array([[x1,y1],[x2,y2],[x3,y3],[x4,y4]]) # 必须是array数组的...
  • 使用python opencv返回点集cnt的最小...举例说明:画一个任意四边形(任意多边形都可以)的最小外接矩形,那么点集cnt 存放的就是该四边形的4个顶点坐标(点集里面有4个点)cnt = np.array([[x1,y1],[x2,y2],[x3,y3],[...
  • 1、方法: 使用python opencv返回点集cnt的最小外接矩形,所用...画一个任意四边形(任意多边形都可以)的最小外接矩形,那么点集cnt 存放的就是该四边形的4个顶点坐标(点集里面有4个点) cnt = np.array([[x1,y...
  • 画一个任意四边形(任意多边形都可以)的最小外接矩形,那么点集cnt 存放的就是该四边形的4个顶点坐标(点集里面有4个点) cnt = np.array([[x1,y1],[x2,y2],[x3,y3],[x4,y4]]) # 必须是array数组的形式 rect = ...
  • 使用python opencv返回点集cnt的最小外接矩形,...举例说明:画一个任意四边形(任意多边形都可以)的最小外接矩形,那么点集cnt 存放的就是该四边形的4个顶点坐标(点集里面有4个点)cnt = np.array([[x1,y1],[x2,y2],...
  • 写在前面:之前是先得到任意四边形最小外接矩形,再使用opencv进行裁剪,但是这样会引入噪声。所以在此记录下,如何直接裁剪原任意四边形区域。 思路: 1.计算要裁剪区域四边形的相对水平方向的旋转角度; 2.将...
  • 需要注意一个概念上的区别,轮廓矩形边界不等于轮廓的最小外接四边形。  轮廓重心同样采用线段表进行计算,分别计算各线段在水平方向和垂直方向上的加权平均,其权重为线段长度。 ...
  • 2.2 背景三角形网格划分 目前流行的二维网格生成算法是推进波前法和 Delaunay 三角划分法。 2.2.1 边界输入 ...图选择一个节点,以使三角形的外接最小,且三角形不与前沿相交。 2.3 四边形网格划分 2.3.1 三
  • Delaunay三角网的空圆特性和最大化最小角特性是需要同时满足吗?还是满足其中一个即可?有没有满足空圆特性不满足...具体的说是指在两个相邻的三角形构成凸四边形的对角线,在相互交换后,六个内角的最小角不再增大。
  • 模板--二维凸包(1)

    2016-04-19 01:21:45
    二维凸包模板: 1.求凸包顶点 2.Graham扫描法 3.判断稳定凸包 4.凸包直径 5.凸包周长及面积 6.凸包内最大三角形面积 7.凸包最小外接矩形面积 8.凸包最小外接平行四边形面积
  • 输入的点云可能存在噪声干扰,需要通过一系列处理去除干扰,并在求到最小外接矩阵后进行优化,才可获得较准确的长和宽。 主要进行如下几个步骤:1)将点云旋转到XOY平面;2)生成点云图像;3)进行膨胀腐蚀,填补...
  • Delaunay三角网生成算法

    万次阅读 2017-12-11 15:52:26
    Delaunay三角网的两个...最大的最小角性质:在由点集S所构成的三角网中,Delaunay三角网中三角形的最小角度是最大的,一个简明的解释:2个相邻三角形构成的凸四边形的对角线在相互交换后,6个内角的最小角不再增大。
  • ACM算法模版大集合

    2009-10-15 23:18:39
    近似O(n)的最小外接圆算法 点集直径 旋转卡壳,对踵点 多边形的三角剖分 数学 / 数论 高精度计算 高数度加减法、乘除法 最大公约数 Euclid算法 扩展的Euclid算法 同余方程 / 二元一次不定方程 同余...
  • LOP优化

    千次阅读 2017-07-03 00:27:14
    Delaunay三角网局部优化算法可以运用最大最小角法则来判断,即在共边的两相邻三角形组成的凸四边形中,将其两条对角线相互交换,判断是否会增加这两个三角形中六个内角的角度值。常用三角形圆周角的性质进行判断。 ...
  • FLASH的HITTEST好像只是HITTEST一个矩形范围,比如说一个平行四边形,它的HITTEST区域就是一个外接最小矩形。能不能改一下,使它按照图形的外轮廓来HITTEST? 在 FLASH 里面有一个 hitTest() 语句,是...
  • ACM 算法模板集

    2018-04-19 20:35:45
    12. 三角形外接圆半径公式 13. 圆內接四边形面积公式 14. 基础数论公式 三. 大数模板,字符读入 四. 数论算法 1. Greatest Common Divisor最大公约数 2. Prime素数判断 3. Sieve Prime素数筛法 4. Module Inverse模...
  • 1 四边形的中高线 2 四圆共点 3 四个内切圆 4 三线共点 5 外接三角形 6 位似 7 经过定点 8 剪成锐角三角形 9 方程帮忙 10 征解问题 11 外公切线围成菱形 l2 射影平分周长 13 勾三股四弦五 14 分断式命题 15 解析几何...

空空如也

空空如也

1 2
收藏数 34
精华内容 13
关键字:

最小外接四边形