This repository has been archived on 2021-02-05. You can view files and clone it, but cannot push or open issues or pull requests.
ipcv/python_notebook/hough.ipynb

137 lines
4.2 KiB
Plaintext
Raw Normal View History

2019-05-14 22:37:19 +07:00
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"import numpy as np\n",
"import imageio\n",
"import math"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"def rgb2gray(rgb):\n",
" return np.dot(rgb[..., :3], [0.299, 0.587, 0.114]).astype(np.uint8)\n",
"\n",
"\n",
"def hough_line(img, angle_step=1, lines_are_white=True, value_threshold=5):\n",
" \"\"\"\n",
" Hough transform for lines\n",
"\n",
" Input:\n",
" img - 2D binary image with nonzeros representing edges\n",
" angle_step - Spacing between angles to use every n-th angle\n",
" between -90 and 90 degrees. Default step is 1.\n",
" lines_are_white - boolean indicating whether lines to be detected are white\n",
" value_threshold - Pixel values above or below the value_threshold are edges\n",
"\n",
" Returns:\n",
" accumulator - 2D array of the hough transform accumulator\n",
" theta - array of angles used in computation, in radians.\n",
" rhos - array of rho values. Max size is 2 times the diagonal\n",
" distance of the input image.\n",
" \"\"\"\n",
" # Rho and Theta ranges\n",
" thetas = np.deg2rad(np.arange(-90.0, 90.0, angle_step))\n",
" width, height = img.shape\n",
" diag_len = int(round(math.sqrt(width * width + height * height)))\n",
" rhos = np.linspace(-diag_len, diag_len, diag_len * 2)\n",
"\n",
" # Cache some resuable values\n",
" cos_t = np.cos(thetas)\n",
" sin_t = np.sin(thetas)\n",
" num_thetas = len(thetas)\n",
"\n",
" # Hough accumulator array of theta vs rho\n",
" accumulator = np.zeros((2 * diag_len, num_thetas), dtype=np.uint8)\n",
" # (row, col) indexes to edges\n",
" are_edges = img > value_threshold if lines_are_white else img < value_threshold\n",
" y_idxs, x_idxs = np.nonzero(are_edges)\n",
"\n",
" # Vote in the hough accumulator\n",
" for i in range(len(x_idxs)):\n",
" x = x_idxs[i]\n",
" y = y_idxs[i]\n",
"\n",
" for t_idx in range(num_thetas):\n",
" # Calculate rho. diag_len is added for a positive index\n",
" rho = diag_len + int(round(x * cos_t[t_idx] + y * sin_t[t_idx]))\n",
" accumulator[rho, t_idx] += 1\n",
"\n",
" return accumulator, thetas, rhos"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"def show_hough_line(img, accumulator, thetas, rhos, save_path=None):\n",
" import matplotlib.pyplot as plt\n",
"\n",
" fig, ax = plt.subplots(1, 2, figsize=(10, 10))\n",
"\n",
" ax[0].imshow(img, cmap=plt.cm.gray)\n",
" ax[0].set_title('Input image')\n",
" ax[0].axis('image')\n",
"\n",
" ax[1].imshow(\n",
" accumulator, cmap='jet',\n",
" extent=[np.rad2deg(thetas[-1]), np.rad2deg(thetas[0]), rhos[-1], rhos[0]])\n",
" ax[1].set_aspect('equal', adjustable='box')\n",
" ax[1].set_title('Hough transform')\n",
" ax[1].set_xlabel('Angles (degrees)')\n",
" ax[1].set_ylabel('Distance (pixels)')\n",
" ax[1].axis('image')\n",
"\n",
" # plt.axis('off')\n",
" if save_path is not None:\n",
" plt.savefig(save_path, bbox_inches='tight')\n",
" plt.show()"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"imgpath = '../images/bangdiem.png'\n",
"img = imageio.imread(imgpath)\n",
"if img.ndim == 3:\n",
" img = rgb2gray(img)\n",
"accumulator, thetas, rhos = hough_line(img)"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.2"
}
},
"nbformat": 4,
"nbformat_minor": 2
}