Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 72 additions & 0 deletions .github/workflows/wheels.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
name: Build Wheels

on: [push, pull_request]

jobs:
build_wheels:
name: Build wheels on ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macOS-latest]
exclude:
# giving up; MSVC linker error seems to be unescapable:
# "unresolved external symbol PyInit_lib"
- os: windows-latest
env:
CIBW_PROJECT_REQUIRES_PYTHON: ">=3.6"

steps:
- uses: actions/checkout@v2

# Used to host cibuildwheel
- uses: actions/setup-python@v2

- name: Install cibuildwheel
run: |
python -m pip install --upgrade pip
python -m pip install cibuildwheel==1.10.0

- name: Build wheels
run: python -m cibuildwheel --output-dir wheelhouse

- uses: actions/upload-artifact@v2
with:
path: ./wheelhouse/*.whl

build_sdist:
name: Build source distribution
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2

- uses: actions/setup-python@v2
name: Install Python
with:
python-version: '3.8'

- name: Build sdist
run: python setup.py sdist

- uses: actions/upload-artifact@v2
with:
path: dist/*.tar.gz

# upload_pypi:
# needs: [build_wheels, build_sdist]
# runs-on: ubuntu-latest
# # upload to PyPI on every tag starting with 'v'
# # if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags/v')
# # alternatively, to publish when a GitHub Release is created, use the following rule:
# if: github.event_name == 'release' && github.event.action == 'published'
# steps:
# - uses: actions/download-artifact@v2
# with:
# name: artifact
# path: dist

# - uses: pypa/gh-action-pypi-publish@master
# with:
# user: __token__
# password: ${{ secrets.pypi_password }}
# # To test: repository_url: https://test.pypi.org/legacy/
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
build
dist
*egg-info
__pycache__
Binary file modified example/PIL_house.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 5 additions & 7 deletions example/example_PIL.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,19 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Date : 2015-12-19 02:09:53
# @Author : Gefu Tang (tanggefu@gmail.com)
# @Link : https://github.com/primetang/pylsd
# @Version : 0.0.1

import os

from PIL import Image, ImageDraw
import numpy as np
import os
from pylsd import lsd
from pylsd.lsd import lsd

fullName = 'house.png'
folder, imgName = os.path.split(fullName)
img = Image.open(fullName)
gray = np.asarray(img.convert('L'))
lines = lsd(gray)
draw = ImageDraw.Draw(img)
for i in xrange(lines.shape[0]):
for i in range(lines.shape[0]):
pt1 = (int(lines[i, 0]), int(lines[i, 1]))
pt2 = (int(lines[i, 2]), int(lines[i, 3]))
width = lines[i, 4]
Expand Down
6 changes: 1 addition & 5 deletions example/example_cv2.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Date : 2015-12-19 02:09:53
# @Author : Gefu Tang (tanggefu@gmail.com)
# @Link : https://github.com/primetang/pylsd
# @Version : 0.0.1

import cv2
import numpy as np
import os
from pylsd import lsd
from pylsd.lsd import lsd
fullName = 'car.jpg'
folder, imgName = os.path.split(fullName)
src = cv2.imread(fullName, cv2.IMREAD_COLOR)
Expand Down
54 changes: 13 additions & 41 deletions pylsd/bindings/lsd_ctypes.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,49 +7,21 @@

import ctypes
import os
import sys
import random
import numpy as np

import glob

def load_lsd_library():

root_dir = os.path.abspath(os.path.dirname(__file__))

libnames = ['linux/liblsd.so']
libdir = 'lib'
if sys.platform == 'win32':
if sys.maxsize > 2 ** 32:
libnames = ['win32/x64/lsd.dll', 'win32/x64/liblsd.dll']
else:
libnames = ['win32/x86/lsd.dll', 'win32/x86/liblsd.dll']
elif sys.platform == 'darwin':
libnames = ['darwin/liblsd.dylib']

while root_dir != None:
for libname in libnames:
try:
lsdlib = ctypes.cdll[os.path.join(root_dir, libdir, libname)]
return lsdlib
except Exception as e:
pass
tmp = os.path.dirname(root_dir)
if tmp == root_dir:
root_dir = None
else:
root_dir = tmp

# if we didn't find the library so far, try loading without
# a full path as a last resort
for libname in libnames:
try:
# print "Trying",libname
lsdlib = ctypes.cdll[libname]
return lsdlib
except:
pass

return None
# may fail if CWD (via sys.path) contains pylsd/bindings/__init__.py,
# but otherwise contains the auto-built library for this platform/installation:
lib_dir = os.path.dirname(os.path.dirname(__file__))
lib_path = None
for lib_name in ['lib.*.so', 'lib.*.dll', 'lib.*.dylib', 'lib.*.lib']:
libs = glob.glob(os.path.join(lib_dir, lib_name))
if libs:
lib_path = libs[0]
break
if not lib_path:
return None
return ctypes.cdll[lib_path]

lsdlib = load_lsd_library()
if lsdlib == None:
Expand Down
Binary file removed pylsd/lib/darwin/liblsd.dylib
Binary file not shown.
Binary file removed pylsd/lib/linux/liblsd.so
Binary file not shown.
Binary file removed pylsd/lib/win32/x64/lsd.dll
Binary file not shown.
94 changes: 62 additions & 32 deletions pylsd/lsd.py
Original file line number Diff line number Diff line change
@@ -1,32 +1,62 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Date : 2015-12-19 02:09:53
# @Author : Gefu Tang (tanggefu@gmail.com)
# @Link : https://github.com/primetang/pylsd
# @Version : 0.0.1

from .bindings.lsd_ctypes import *


def lsd(src):
rows, cols = src.shape
src = src.reshape(1, rows * cols).tolist()[0]

temp = os.path.abspath(str(np.random.randint(
1, 1000000)) + 'ntl.txt').replace('\\', '/')

lens = len(src)
src = (ctypes.c_double * lens)(*src)
lsdlib.lsdGet(src, ctypes.c_int(rows), ctypes.c_int(cols), temp)

fp = open(temp, 'r')
cnt = fp.read().strip().split(' ')
fp.close()
os.remove(temp)

count = int(cnt[0])
dim = int(cnt[1])
lines = np.array([float(each) for each in cnt[2:]])
lines = lines.reshape(count, dim)

return lines
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import ctypes
import os
import sys
from tempfile import NamedTemporaryFile

import numpy as np


from .bindings.lsd_ctypes import lsdlib

def lsd(src, scale=0.8, sigma_scale=0.6, quant=2.0, ang_th=22.5, eps=0.0, density_th=0.7, n_bins=1024, max_grad=255.0):
"""Analyse image with Line Segment Detector.

Args:
src (Numpy object) : 2-d grayscale image array (HxW) to analyse.

Keyword Args:
scale (double) : Scale the image by Gaussian filter.
sigma_scale (double) : Sigma for Gaussian filter is computed as sigma = sigma_scale/scale.
quant (double) : Bound to the quantization error on the gradient norm.
ang_th (double) : Gradient angle tolerance in degrees.
eps (double) : Detection threshold, -log10(NFA).
density_th (double) : Minimal density of region points in rectangle.
n_bins (int) : Number of bins in pseudo-ordering of gradient modulus.
max_grad (double) : Gradient modulus in the highest bin. The default value corresponds to the highest gradient modulus on images with gray levels in [0,255].

Returns:
A list of line candidates as 5-tuples of (x1, y1, x2, y2, width).
"""
rows, cols = src.shape
src = src.reshape(1, rows * cols).tolist()[0]

lens = len(src)
src = (ctypes.c_double * lens)(*src)

with NamedTemporaryFile(prefix='pylsd-', suffix='.ntl.txt', delete=False) as fp:
fname = fp.name
fname_bytes = bytes(fp.name) if sys.version_info < (3, 0) else bytes(fp.name, 'utf8')

lsdlib.lsdGet(src, ctypes.c_int(rows), ctypes.c_int(cols), fname_bytes,
ctypes.c_double(scale),
ctypes.c_double(sigma_scale),
ctypes.c_double(quant),
ctypes.c_double(ang_th),
ctypes.c_double(eps),
ctypes.c_double(density_th),
ctypes.c_int(n_bins),
ctypes.c_double(max_grad))

with open(fname, 'r') as fp:
output = fp.read()
cnt = output.strip().split(' ')
count = int(cnt[0])
dim = int(cnt[1])
lines = np.array([float(each) for each in cnt[2:]])
lines = lines.reshape(count, dim)

os.remove(fname)
return lines
1 change: 1 addition & 0 deletions requirements.test.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
opencv-python>=3.4
28 changes: 18 additions & 10 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,31 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Date : 2015-12-19 02:09:53
# @Date : 2019-01-08 09:32:00
# @Author : Gefu Tang (tanggefu@gmail.com)
# @Link : https://github.com/primetang/pylsd
# @Version : 0.0.1
# @Version : 0.0.3

from setuptools import setup
from setuptools import setup, Extension

clib = Extension('pylsd.lib',
sources=['source/src/lsd.cpp'],
include_dirs=['source/include'],
depends=['source/include/lsd.h'],
language="c++")

setup(
name='pylsd',
version='0.0.1',
version='0.0.4',
description='pylsd is the python bindings for LSD - Line Segment Detector',
long_description=open('README.md').read(),
long_description_content_type='text/markdown',
author='Gefu Tang',
author_email='tanggefu@gmail.com',
maintainer='kba',
license='BSD',
keywords="LSD",
url='https://github.com/primetang/pylsd',
packages=['pylsd', 'pylsd.bindings', 'pylsd.lib'],
package_dir={'pylsd.lib': 'pylsd/lib'},
package_data={'pylsd.lib': [
'darwin/*.dylib', 'win32/x86/*.dll', 'win32/x64/*.dll', 'linux/*.so']},
keywords=["LSD", 'line segmentation'],
url='https://github.com/kba/pylsd',
packages=['pylsd', 'pylsd.bindings'],
install_requires=['numpy'],
ext_modules=[clib],
)
11 changes: 0 additions & 11 deletions source/CMakeLists.txt

This file was deleted.

6 changes: 3 additions & 3 deletions source/include/lsd.h
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ ntuple_list LineSegmentDetection( image_double image, double scale,

@return a 5-tuple list of detected line segments.
*/
ntuple_list lsd_scale(image_double image, double scale);
ntuple_list lsd_scale(image_double image, double scale, double sigma_scale, double quant, double ang_th, double eps, double density_th, int n_bins, double max_grad);

/*----------------------------------------------------------------------------*/
/* LSD Simple Interface */
Expand All @@ -263,10 +263,10 @@ ntuple_list lsd_scale(image_double image, double scale);

@return a 5-tuple list of detected line segments.
*/
ntuple_list lsd(image_double image);
ntuple_list lsd(image_double image, double scale, double sigma_scale, double quant, double ang_th, double eps, double density_th, int n_bins, double max_grad);


extern "C" LSD_EXPORT void lsdGet(double* src, int rows, int cols, char* file);
extern "C" LSD_EXPORT void lsdGet(double* src, int rows, int cols, char* file, double scale, double sigma_scale, double quant, double ang_th, double eps, double density_th, int n_bins, double max_grad);

#endif /* !LSD_HEADER */
/*----------------------------------------------------------------------------*/
Loading