"""Calibrate cameras using a checkerboard or circle dot board. This uses
the OpenCV computer vision library to actually do the hard work.
"""

import numpy as np
import cv2
import glob

import functools
from multiprocessing import Pool


def find_objp(gridsize, dims):
    """Make an array of the object points for the grid.

    Parameters
    ----------
    gridsize : float
        Distance between circles or length of checkerboard corners
        in whatever physical units you are using.
    dims : tuple
        (width, height) of the circle grid pattern or the inner
        dimension of the checkerboard.

    Returns
    -------
    npts : int
        Number of grid calibration points
    objp : list of an array array (npts x 3)
        Physical location of the circles or corners in a plane.
    """

    npts = dims[0] * dims[1]

    objp = np.zeros((dims[0] * dims[1], 3), np.float32)
    objp[:, :2] = np.mgrid[0:dims[0], 0:dims[1]].T.reshape(-1, 2)

    return npts, [objp * gridsize]


def load_images(path, func):
    """Read in images as numpy arrays and store in a list.
    """

    def _loader(fname):
        return func(cv2.imread(fname, flags=cv2.CV_LOAD_IMAGE_GRAYSCALE))

    return map(_loader, path)


def _find_circles(img, dims):
    """Find the circle grid locations from an image.

    """

    ret, circ = cv2.findCirclesGrid(img, dims, flags=cv2.CALIB_CB_SYMMETRIC_GRID)

    return ret, circ

def parallel_circ_find(images, dims, nproc=4):
    """Use multiprocessing module to find circle pattern