下文的代码可能展示不全,详情请下载文件:用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(广度优先搜索)的更多相关文章

  1. Python调用ansible API系列(二)执行adhoc和playbook

    执行adhoc #!/usr/bin/env python # -*- coding: utf-8 -*- import sys from collections import namedtuple ...

  2. python3.4学习笔记(二十五) Python 调用mysql redis实例代码

    python3.4学习笔记(二十五) Python 调用mysql redis实例代码 #coding: utf-8 __author__ = 'zdz8207' #python2.7 import ...

  3. python3.4学习笔记(二十三) Python调用淘宝IP库获取IP归属地返回省市运营商实例代码

    python3.4学习笔记(二十三) Python调用淘宝IP库获取IP归属地返回省市运营商实例代码 淘宝IP地址库 http://ip.taobao.com/目前提供的服务包括:1. 根据用户提供的 ...

  4. python调用系统命令popen、system

    python调用Shell脚本,有两种方法:os.system(cmd)或os.popen(cmd),前者返回值是脚本的退出状态码,后者的返回值是脚本执行过程中的输出内容.所以说一般我们认为popen ...

  5. Python的扩展接口[3] -> Matlab引擎 -> 使用 Python 调用 Matlab 程序

    Python - Matlab 目录 Python-Matlab 引擎 Python-Matlab 数组 Python-Matlab 基本操作 Python-Matlab 调用 m 文件 Matlab ...

  6. Python调用Java代码部署及初步使用

    Python调用Java代码部署: jpype下载地址:https://www.lfd.uci.edu/~gohlke/pythonlibs/#jpype 下载的时候需要使用Chrome浏览器进行下载 ...

  7. Windows中使用 Python 调用 Matlab 程序

    https://ww2.mathworks.cn/help/matlab/matlab_external/system-and-configuration-requirements.html http ...

  8. Python调用R编程——rpy2

    在Python调用R,最常见的方式是使用rpy2模块. 简介 模块 The package is made of several sub-packages or modules: rpy2.rinte ...

  9. python调用其他程序或脚本方法(转)

    python运行(调用)其他程序或脚本 在Python中可以方便地使用os模块运行其他的脚本或者程序,这样就可以在脚本中直接使用其他脚本,或者程序提供的功能,而不必再次编写实现该功能的代码.为了更好地 ...

随机推荐

  1. Git实战指南----跟着haibiscuit学Git(第八篇)

    笔名:  haibiscuit 博客园: https://www.cnblogs.com/haibiscuit/ Git地址: https://github.com/haibiscuit?tab=re ...

  2. Docker 底层技术与端口映射

    容器底层实现技术  1.cgroup 实现了资源的限额:CPU,内存,硬盘 cgroup使用  docker run -d -m 100M httpd 2.namespace 实现了资源隔离 name ...

  3. LeetCode刷题191124

    博主渣渣一枚,刷刷leetcode给自己瞅瞅,大神们由更好方法还望不吝赐教.题目及解法来自于力扣(LeetCode),传送门. 算法: 给出一个无重叠的 ,按照区间起始端点排序的区间列表. 在列表中插 ...

  4. Samba共享文件

    1 安装samba yum install -y samba* 2 添加用户 useradd smbuser 3 设置共享文件用户的密码 smbpasswd -a smbuser 4 创建公共共享文件 ...

  5. JS原型链与instanceof底层原理

    一.问题: instanceof 可以判断一个引用是否属于某构造函数: 另外,还可以在继承关系中用来判断一个实例是否属于它的父类型. 老师说:instanceof的判断逻辑是: 从当前引用的proto ...

  6. (转)Ioc控制反转和依赖注入

    转载地址:https://zhuanlan.zhihu.com/p/95869440 控制反转控制反转(Inversion of Control,简称IoC),是面向对象编程中的一种设计思想,其作用是 ...

  7. 字典树(Trie)详解

    详解字典树(Trie) 本篇随笔简单讲解一下信息学奥林匹克竞赛中的较为常用的数据结构--字典树.字典树也叫Trie树.前缀树.顾名思义,它是一种针对字符串进行维护的数据结构.并且,它的用途超级广泛.建 ...

  8. C++之指针和引用

    指针和引用的异同点总结 异同点 指针 引用 1 指针是一个变量,本身是一个实体,指针中的内容是一个地址值 该值指向内存中的一个存储单元 引用只是一个别名,实质上指向同一对象 系统不为引用分配内存 2 ...

  9. Java堆空间Vs栈内存

    之前我写了几篇有关Java垃圾收集的文章之后,我收到了很多电子邮件,请求解释Java堆空间,Java栈内存,Java中的内存分配以及它们之间的区别. 您可能在Java,Java EE书籍和教程中看到很 ...

  10. 实现用SQL查询连续发文天数/连续登录天数

    当月最长连续发文天数: //临时:id_time_table: select distinct app_id, from_unixtime(create_date_time, 'yyyy-MM-dd' ...