我在Python中丢的面子被我用C++找回来了

简介: 我在Python中丢的面子被我用C++找回来了

前言

  在我初涉编程世界的时候,Python是我的初恋。它的语法简洁明了,易于上手,也能快速上手。我记得那时候,然而,随着时间的推移,我发现Python在处理一些复杂任务时,效率低下的问题开始显现。于是,毫无疑问我选择了C++。我开始用C++重新实现那些曾经用Python完成的任务。结果出乎我的意料,C++的效率竟然比Python高出许多。这让我有些惊讶,也有些尴尬。我曾经以为Python是我的最佳伴侣,现在我说吃了细粮后怎么能咽的下粗糠!

问题

  在图像处理任务中有一个经典任务:电子围栏。电子围栏,顾名思义就是在视频画面中出现绘制一个多边形的区域,该区域的边数应该是为 >=3,当目标出现在视频画面中的时候触碰到围栏时候或者在围栏里面则进行告警。

  在进行目标检测时常见的为矩形,矩形的坐标形式是Xmin, Ymin, Xmax, Ymax,多边形的坐标形式为 [(x1,y1), (x2,y2), (x3,y3) ...] 这里我们需要判断这两个多边形是否存在交集

Python解决

  使用Python的话针对上述任务经过调用研究,可以直接调用现成的shapely.geometry库进行运算,我们构建isRectangleAndPolygonIntersect 函数可以直接把目标框的坐标与电子围栏的坐标输入到对应位置调用库函数即可直接得出目标区域与电子围栏区域是否存在交集。

ini

复制代码

import time
from shapely.geometry import Polygon, box
def isRectangleAndPolygonIntersect(label, warn):
    # 创建矩形坐标域对象
    rect = box(label[0], label[1], label[2], label[3])
    # 创建多边形对象
    polygon = Polygon(warn)
    if rect.intersects(polygon):
        return 1  # 相交
    else:
        return 0  # 不相交
if __name__ == "__main__":
    label = [0,0,2,2]
    warn = [(3,3),(10,3),(10,10),(3,10)]
    t1 = time.time()
    for i in range(1000000):
        isRectangleAndPolygonIntersect(label, warn)
    print(time.time() - t1)

C++解决

  相较于Python使用C++就没有那么多库进行调用(可能是自己知道的库较少的缘故),这就需要自己从底层逻辑中进行分析得到判断矩形和多边形是否存在交集:

  1. 矩形与多边形相交则必定存在矩形内的点在多边形区域内;
  2. 矩形内的区域点可以很好使用for循环得到;
  3. 可以通过射线法判断某点是否在多边形内;

射线法基本原理

  在上述逻辑里有一个基础知识点:射线法。下面为大家介绍其基本原理: 从待检测点P出发,沿任意方向(通常选择水平方向以简化计算)绘制一条射线(无限长直线),穿过整个平面。 计算这条射线与多边形各边的交点数目(包括边界上的交点,但不包括在多边形顶点处的重复交点)。根据交点数目的奇偶性来判断点P的位置:

  1. 若交点数目为奇数,则点P位于多边形内部;
  2. 若交点数目为偶数,则点P位于多边形外部。

ini

复制代码

#include <iostream>
#include <vector>
#include <time.h>
//#include <algorithm>
using namespace std;
//定义电子围栏的坐标点
struct Point {
    int x;
    int y;
};
//定义目标检测框的坐标点
struct Box {
    int xmin;
    int ymin;
    int xmax;
    int ymax;
};
// 获取目标检测狂的坐标
Box get_box(int xmin, int ymin, int xmax, int ymax) {
    Box label_box = {xmin, ymin, xmax, ymax };
    return label_box;
}
//获取电子围栏坐标
vector<Point> get_warn_box() {
    vector<Point> warn_box = { {3, 3},{10,3},{10,10},{3,10} };
    return warn_box;
}
//射线法求某点是否在多边形区域内
bool isPointInPolygon(const Point& p, const vector<Point>& polygon) {
    int n = polygon.size();
    int count = 0;
    for (int i = 0; i < n; ++i) {
        Point p1 = polygon[i];
        Point p2 = polygon[(i + 1) % n];
        if (p1.y == p2.y) continue;
        if (p.y < min(p1.y, p2.y)) continue;
        if (p.y >= max(p1.y, p2.y)) continue;
        double x = (double)(p.y - p1.y) * (p2.x - p1.x) / (p2.y - p1.y) + p1.x;
        if (x > p.x) count++;
    }
    return count % 2 == 1;
}
// 判定是否非相离状态
bool isRectangleAndPolygonIntersect(const Box& label_box, const vector<Point>& warn_box) {
    Point p;
    bool isRect = false;
    for (int x = label_box.xmin; x <= label_box.xmax; ++x) {
        for (int y = label_box.ymin; y <= label_box.ymax; ++y) {
            p = { x, y };
            isRect = isPointInPolygon(p, warn_box);
            if (isRect) break;
        }
        if (isRect) break;
    }
    return isRect;
}
int main() {
    Box label_box;  //定义 Box label_box 常量
    label_box = get_box(0, 0, 2, 2); //调用函数得到
    vector<Point> warn_box;
    warn_box = get_warn_box();
    clock_t start, finish;
    start = clock();
    /*
    cout << "warn_box: ";
    for (const auto& point : warn_box) {
        cout << "(" << point.x << ", " << point.y << ") ";
    }
    cout << endl;
    */
    for (int x = 0; x <= 1000000; x++) {
        bool isRect;
        isRect = isRectangleAndPolygonIntersect(label_box, warn_box);
    }
    finish = clock();
    cout << endl << "the time cost is:" << double(finish - start) / CLOCKS_PER_SEC << endl;
    
    return 0;
}

比对

  通过上述的Python代码和C++代码我们可以明显得到二者的矩形坐标与多边形坐标是一样的,二者循环次数也是一样的

  1. Python代码运行一百万次的平均耗时为39.5秒
  2. C++代码运行一百万次的平均耗时为0.535秒

                    

老天爷!这是什么概念?我的表情就像上面的杰克版。请你不要告诉我python还能优化,使用python的人员无非就是图它的方便能快速找到对应的轮子函数进行计算加速开发速度,有优化的时间用来写C++不香么。泪目,在相同的设备中运行,C++ 的运行速度比Python运行速度快了73.8倍。我在Python中丢的面子被我用C++找回来了。重新拾回了男人的尊严!

相关文章
|
3月前
|
算法框架/工具 C++ Python
根据相机旋转矩阵求解三个轴的旋转角/欧拉角/姿态角 或 旋转矩阵与欧拉角(Euler Angles)之间的相互转换,以及python和C++代码实现
根据相机旋转矩阵求解三个轴的旋转角/欧拉角/姿态角 或 旋转矩阵与欧拉角(Euler Angles)之间的相互转换,以及python和C++代码实现
231 0
|
4月前
|
编译器 开发工具 C++
【Python】已解决error: Microsoft Visual C++ 14.0 or greater is required. Get it with “Microsoft C++ Build
【Python】已解决error: Microsoft Visual C++ 14.0 or greater is required. Get it with “Microsoft C++ Build
1958 0
|
1月前
|
C++ Python
探索Python与C/C++混合编程的艺术
探索Python与C/C++混合编程的艺术
36 1
WK
|
2月前
|
机器学习/深度学习 Java 程序员
为什么Python比C++慢很多?
Python相较于C++较慢主要体现在:动态类型系统导致运行时需解析类型,增加开销;作为解释型语言,逐行转换字节码的过程延长了执行时间;自动内存管理和垃圾回收机制虽简化操作但也带来了额外负担;全局解释器锁(GIL)限制了多线程性能;尽管Python库方便灵活,但在性能上往往不及C++底层库。然而,Python在某些领域如数据分析、机器学习中,凭借其高级别抽象和简洁语法仍表现出色。选语言需依据具体应用场景和需求综合考量。
WK
74 1
|
3月前
|
Unix C语言 C++
Python调用C/C++
Python调用C/C++
25 2
|
3月前
|
PHP C++ Python
右手坐标系,空间点绕轴旋转公式&程序(Python和C++程序)
右手坐标系,空间点绕轴旋转公式&程序(Python和C++程序)
63 0
WK
|
3月前
|
机器学习/深度学习 运维 Java
Python 相对于 C++ 有哪些明显的优势
C++是一种强大且高效的编程语言,被广泛应用在系统软件、游戏开发、嵌入式系统等多个领域。然而Python在某些方面展现出显著优势:Python语法简洁直观,易于学习与使用,提高了代码的可读性和团队协作效率;拥有丰富的第三方库和框架资源,能有效提升开发效率;具备良好的跨平台性,无需大量修改即可适应不同操作系统;
WK
52 0
|
4月前
|
算法 Java C++
C++和Python在内存管理上的主要区别是什么?
【7月更文挑战第2天】C++和Python在内存管理上的主要区别是什么?
116 1
|
4月前
|
存储 Java 程序员
Python和C++在内存管理方面有什么不同?
【7月更文挑战第2天】Python和C++在内存管理方面有什么不同?
85 0
|
4月前
|
Java C++ 开发者
如何根据项目需求选择使用C++还是Python进行内存管理?
【7月更文挑战第2天】如何根据项目需求选择使用C++还是Python进行内存管理?
47 0