def Pcn(x, dsz, Nv, dimN=2, dimC=1, crp=False, zm=False):
    """Constraint set projection for convolutional dictionary update
    problem.

    Parameters
    ----------
    x  : array_like
      Input array
    dsz : tuple
      Filter support size(s), specified using the same format as the `dsz`
      parameter of :func:`bcrop`
    Nv : tuple
      Sizes of problem spatial indices
    dimN : int, optional (default 2)
      Number of problem spatial indices
    dimC : int, optional (default 1)
      Number of problem channel indices
    crp : bool, optional (default False)
      Flag indicating whether the result should be cropped to the support
      of the largest filter in the dictionary.
    zm : bool, optional (default False)
      Flag indicating whether the projection function should include
      filter mean subtraction

    Returns
    -------
    y : ndarray
      Projection of input onto constraint set
    """

    if crp:
        def zpadfn(x):
            return x
    else:
        def zpadfn(x):
            return zpad(x, Nv)

    if zm:
        def zmeanfn(x):
            return zeromean(x, dsz, dimN)
    else:
        def zmeanfn(x):
            return x

    return normalise(zmeanfn(zpadfn(bcrop(x, dsz, dimN))), dimN + dimC)