python调用C++实例:用C++对numpy执行BFS(广度优先搜索)
下文的代码可能展示不全,详情请下载文件:用cpp遍历ndarray.rar
问题背景:
现在我有一张二值图test.npy,需要对其闭区域进行孔洞填充,如下图所示:
文件下载链接:用cpp遍历ndarray.rar
用python实现BFS:
def bfs1(im, vis, x, y, xb, yb):
def legal(tx, ty):
if tx < xb and tx >= and ty < yb and ty >= :
return True
else:
return False dx = [, , , -]
dy = [, -, , ]
q = Queue()
ls = []
q.put((x, y))
flag = True
while not q.empty():
tmp = q.get()
cx, cy = tmp
vis[cx][cy] =
for i in range(, ):
tx = cx + dx[i]
ty = cy + dy[i]
if (legal(tx, ty)):
if im[tx][ty] == and vis[tx][ty] == :
q.put((tx, ty))
ls.append((tx, ty))
vis[tx][ty] =
else:
flag = False
if flag:
for pt in ls:
tx, ty = pt
im[tx][ty] = def fillHolePy(im):
x, y = im.shape[:]
ans=im.copy()
vis = np.zeros([x, y])
for i in range(, x):
for j in range(, y):
if vis[i][j] == : # and im[i][j]==
bfs1(ans, vis, i, j, x, y)
return ans
程序执行了0.914秒
用C++实现BFS:(因为python向cpp传参只能用一维数组,这涉及到多维数组到一维数组的映射,详见我的另一篇博客:numpy中多维数组的绝对索引)
int x_s,y_s; inline int MAP(int x,int y){
return y_s*x + y;
} int dx[]={, , , -};
int dy[]={, -, , };
int vis[*]; typedef struct Pt
{
int x,y;
Pt(int x,int y):x(x),y(y){
}
}Pt; bool legal(int x,int y){
if(x<x_s && x>= && y<y_s && y>=)
return true;
return false;
} void bfs(int *img,int x,int y){
queue<Pt> q;
vector<Pt> v;
q.push(Pt(x,y));
bool flag=;
int i;
while(!q.empty()){
Pt pt=q.front();
q.pop();
vis[MAP(x,y)]=;
int cx=pt.x,cy=pt.y;
FF(i,){
int tx=cx+dx[i];
int ty=cy+dy[i];
if(legal(tx,ty)){
if(img[MAP(tx,ty)]== && vis[MAP(tx,ty)]==){
q.push(Pt(tx,ty));
v.push_back(Pt(tx,ty));
vis[MAP(tx,ty)]=;
}
}else{
flag=;
}
}
if(flag){
int sz=v.size();
FF(i,sz){
int & tx=v[i].x;
int & ty=v[i].y;
img[MAP(tx,ty)]=;
}
}
}
} void fillHole(int * img,int X,int Y){
x_s=X,y_s=Y;
int i,j;
FF(i,x_s)FF(j,x_s)if(!vis[MAP(i,j)]){
bfs(img,i,j);
}
}
下面我们看怎样用python调用cpp。
在上文的cpp中,对想要执行的函数fillHole进行声明:
extern "C" {
__declspec(dllexport)
void fillHole(int * img,int X,int Y)
;
}
用g++(mingw64位)编译为dll:
g++ bfs.cpp -shared -o bfs.dll -Wl,--out-implib,bfs.lib
pause
在python中使用numpy的封装加载DLL并且传参调用:
import numpy.ctypeslib as npct def fillHoleCpp(im):
array_2d_int32 = npct.ndpointer(dtype=np.int32, ndim=2, flags='CONTIGUOUS')
dll = npct.load_library("bfs.dll",".")
bfs=dll.fillHole
bfs.restype = None
bfs.argtypes = [array_2d_int32, c_int, c_int]
im=im.astype(dtype=np.int32)
if not im.flags['C_CONTIGUOUS']:
im = np.ascontiguous(im, dtype=im.dtype)
X, Y=im.shape
bfs(im,X,Y)
return im
查看测试结果:
程序执行了0.058秒
根据测试cpp比python快了15倍。
cpp完整代码:
#include <stdio.h>
#include <vector>
#include <queue>
#include <algorithm> using namespace std; #define FF(a,b) for(a=0;a<b;a++) extern "C" {
__declspec(dllexport)
void fillHole(int * img,int X,int Y)
;
} int x_s,y_s; inline int MAP(int x,int y){
return y_s*x + y;
} int dx[]={, , , -};
int dy[]={, -, , };
int vis[*]; typedef struct Pt
{
int x,y;
Pt(int x,int y):x(x),y(y){
}
}Pt; bool legal(int x,int y){
if(x<x_s && x>= && y<y_s && y>=)
return true;
return false;
} void bfs(int *img,int x,int y){
queue<Pt> q;
vector<Pt> v;
q.push(Pt(x,y));
bool flag=;
int i;
while(!q.empty()){
Pt pt=q.front();
q.pop();
vis[MAP(x,y)]=;
int cx=pt.x,cy=pt.y;
FF(i,){
int tx=cx+dx[i];
int ty=cy+dy[i];
if(legal(tx,ty)){
if(img[MAP(tx,ty)]== && vis[MAP(tx,ty)]==){
q.push(Pt(tx,ty));
v.push_back(Pt(tx,ty));
vis[MAP(tx,ty)]=;
}
}else{
flag=;
}
}
if(flag){
int sz=v.size();
FF(i,sz){
int & tx=v[i].x;
int & ty=v[i].y;
img[MAP(tx,ty)]=;
}
}
}
} void fillHole(int * img,int X,int Y){
x_s=X,y_s=Y;
int i,j;
FF(i,x_s)FF(j,x_s)if(!vis[MAP(i,j)]){
bfs(img,i,j);
}
} //int main() {
// return 0;
//}
bfs.cpp
python完整代码:
import numpy as np
import numpy.ctypeslib as npct
import pylab as plt
from queue import Queue
import datetime
from ctypes import * def bfs1(im, vis, x, y, xb, yb):
def legal(tx, ty):
if tx < xb and tx >= 0 and ty < yb and ty >= 0:
return True
else:
return False dx = [0, 0, 1, -1]
dy = [1, -1, 0, 0]
q = Queue()
ls = []
q.put((x, y))
flag = True
while not q.empty():
tmp = q.get()
cx, cy = tmp
vis[cx][cy] = 1
for i in range(0, 4):
tx = cx + dx[i]
ty = cy + dy[i]
if (legal(tx, ty)):
if im[tx][ty] == 0 and vis[tx][ty] == 0:
q.put((tx, ty))
ls.append((tx, ty))
vis[tx][ty] = 1
else:
flag = False
if flag:
for pt in ls:
tx, ty = pt
im[tx][ty] = 255 def fillHolePy(im):
x, y = im.shape[:2]
ans=im.copy()
vis = np.zeros([x, y])
for i in range(0, x):
for j in range(0, y):
if vis[i][j] == 0: # and im[i][j]==0
bfs1(ans, vis, i, j, x, y)
return ans import numpy.ctypeslib as npct def fillHoleCpp(im):
array_2d_int32 = npct.ndpointer(dtype=np.int32, ndim=2, flags='CONTIGUOUS')
dll = npct.load_library("bfs.dll",".")
bfs=dll.fillHole
bfs.restype = None
bfs.argtypes = [array_2d_int32, c_int, c_int]
im=im.astype(dtype=np.int32)
if not im.flags['C_CONTIGUOUS']:
im = np.ascontiguous(im, dtype=im.dtype)
X, Y=im.shape
bfs(im,X,Y)
return im if __name__ == '__main__':
img=np.load('test.npy')
plt.subplot(121)
plt.title('before fill')
plt.imshow(img)
starttime = datetime.datetime.now()
img=fillHoleCpp(img) #使用BFS(广度优先搜索算法)对原图像进行处理
endtime = datetime.datetime.now()
print("程序执行了%.03f秒" % ((endtime - starttime).microseconds / 1000000))
# exit(0)
plt.subplot(122)
plt.title('after fill')
plt.imshow(img)
plt.show()
dealArray.py
参考资料:
https://segmentfault.com/a/1190000000479951
python调用C++实例:用C++对numpy执行BFS(广度优先搜索)的更多相关文章
- Python调用ansible API系列(二)执行adhoc和playbook
执行adhoc #!/usr/bin/env python # -*- coding: utf-8 -*- import sys from collections import namedtuple ...
- python3.4学习笔记(二十五) Python 调用mysql redis实例代码
python3.4学习笔记(二十五) Python 调用mysql redis实例代码 #coding: utf-8 __author__ = 'zdz8207' #python2.7 import ...
- python3.4学习笔记(二十三) Python调用淘宝IP库获取IP归属地返回省市运营商实例代码
python3.4学习笔记(二十三) Python调用淘宝IP库获取IP归属地返回省市运营商实例代码 淘宝IP地址库 http://ip.taobao.com/目前提供的服务包括:1. 根据用户提供的 ...
- python调用系统命令popen、system
python调用Shell脚本,有两种方法:os.system(cmd)或os.popen(cmd),前者返回值是脚本的退出状态码,后者的返回值是脚本执行过程中的输出内容.所以说一般我们认为popen ...
- Python的扩展接口[3] -> Matlab引擎 -> 使用 Python 调用 Matlab 程序
Python - Matlab 目录 Python-Matlab 引擎 Python-Matlab 数组 Python-Matlab 基本操作 Python-Matlab 调用 m 文件 Matlab ...
- Python调用Java代码部署及初步使用
Python调用Java代码部署: jpype下载地址:https://www.lfd.uci.edu/~gohlke/pythonlibs/#jpype 下载的时候需要使用Chrome浏览器进行下载 ...
- Windows中使用 Python 调用 Matlab 程序
https://ww2.mathworks.cn/help/matlab/matlab_external/system-and-configuration-requirements.html http ...
- Python调用R编程——rpy2
在Python调用R,最常见的方式是使用rpy2模块. 简介 模块 The package is made of several sub-packages or modules: rpy2.rinte ...
- python调用其他程序或脚本方法(转)
python运行(调用)其他程序或脚本 在Python中可以方便地使用os模块运行其他的脚本或者程序,这样就可以在脚本中直接使用其他脚本,或者程序提供的功能,而不必再次编写实现该功能的代码.为了更好地 ...
随机推荐
- 松软科技web课堂:JavaScript 比较和逻辑运算符
JavaScript 比较和逻辑运算符 比较和逻辑运算符用于测试 true 或 false. 比较运算符 比较运算符在逻辑语句中使用,以判定变量或值是否相等. 我们给定 x = 5,下表中解释了比较运 ...
- epub.js的使用
epub.js的使用 npm安装 npm install epubjs epub阅读器开发 ePub电子书解析和渲染 生成Book对象 this.book = new Epub(DOWNLOAD_UR ...
- XSS劫持cookie登录
<script>alert (document.cookie)</script> 获取cookie 实验环境用的DVWA 先用系统账号登录,admin password ...
- 在Dynamics CRM中使用Bootstrap
我是微软Dynamics 365 & Power Platform方面的工程师罗勇,也是2015年7月到2018年6月连续三年Dynamics CRM/Business Solutions方面 ...
- Android数据库GreenDao的使用总结
一.GreenDao的介绍 GreenDAO是一个开源的Android ORM(“对象/关系映射”),通过ORM(称为“对象/关系映射”),节省了我们在数据库开发过程的时间! 通过GreenDao,我 ...
- Android 弹出Dialog时隐藏状态栏和底部导航栏
上代码 dialog.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION); di ...
- PWA学习笔记(二)
设计与体验 APP Shell: 1.应用从显示内容上可粗略划分为内容部分和外壳部分,App Shell 就是外壳部分,即页面的基本结构 2.它不仅包括用户能看到的页面框架部分,还包括用户看不到的代码 ...
- 检测服务器是否开启重协商功能(用于CVE-2011-1473漏洞检测)
背景 由于服务器端的重新密钥协商的开销至少是客户端的10倍,因此攻击者可利用这个过程向服务器发起拒绝服务攻击.OpenSSL 1.0.2及以前版本受影响. 方法 使用OpenSSL(linux系统基本 ...
- 五、如何通过CT三维图像得到DRR图像
一.介绍 获取DRR图像是医疗图像配准里面的一个重要的前置步骤:它的主要目的是,通过CT三维图像,获取模拟X射线影像,这个过程也被称为数字影响重建. 在2D/3D的配准流程里面,需要首先通过CT三维图 ...
- 一个适合于.NET Core的超轻量级工作流引擎:Workflow-Core
一.关于Workflow-Core 近期工作上有一个工作流的开发需求,自己基于面向对象和职责链模式捣鼓了一套小框架,后来在github上发现一个轻量级的工作流引擎轮子:Workflow-Core,看完 ...