'**SUMMARY**
smartThreshold uses a method called grabCut, also called graph cut, to
automagically generate a grayscale mask image. The dumb version of threshold
just uses color, smartThreshold looks at
both color and edges to find a blob. To work smartThreshold needs either a
rectangle that bounds the object you want to find, or a mask. If you use
a rectangle make sure it holds the complete object. In the case of a mask, it
need not be a normal binary mask, it can have the normal white foreground and black
background, but also a light and dark gray values that correspond to areas
that are more likely to be foreground and more likely to be background. These
values can be found in the color class as Color.BACKGROUND, Color.FOREGROUND,
Color.MAYBE_BACKGROUND, and Color.MAYBE_FOREGROUND.
**PARAMETERS**
* *mask* - A grayscale mask the same size as the image using the 4 mask color values
* *rect* - A rectangle tuple of the form (x_position,y_position,width,height)
**RETURNS**
A grayscale image with the foreground / background values assigned to:
* BACKGROUND = (0,0,0)
* MAYBE_BACKGROUND = (64,64,64)
* MAYBE_FOREGROUND =  (192,192,192)
* FOREGROUND = (255,255,255)
**EXAMPLE**
>>> img = Image("RatTop.png")
>>> mask = Image((img.width,img.height))
>>> mask.dl().circle((100,100),80,color=Color.MAYBE_BACKGROUND,filled=True)
>>> mask.dl().circle((100,100),60,color=Color.MAYBE_FOREGROUND,filled=True)
>>> mask.dl().circle((100,100),40,color=Color.FOREGROUND,filled=True)
>>> mask = mask.applyLayers()
>>> new_mask = img.smartThreshold(mask=mask)
>>> new_mask.show()
**NOTES**
http://en.wikipedia.org/wiki/Graph_cuts_in_computer_vision
**SEE ALSO**
:py:meth:`smartFindBlobs`'

def smartThreshold(self, mask=None, rect=None):

    try:
        import cv2
    except:
        logger.warning("Can't    Do    GrabCut    without    OpenCV    >=    2.3.0")
        return
    retVal = []
    if (mask is not None):
        bmp = mask._getGrayscaleBitmap()
        LUT = np.zeros((256, 1), dtype=uint8)
        LUT[255] = 1
        LUT[64] = 2
        LUT[192] = 3
        cv.LUT(bmp, bmp, cv.fromarray(LUT))
        mask_in = np.array(cv.GetMat(bmp))
        npimg = np.array(cv.GetMat(self.getBitmap()))
        tmp1 = np.zeros((1, (13 * 5)))
        tmp2 = np.zeros((1, (13 * 5)))
        cv2.grabCut(npimg, mask_in, None, tmp1, tmp2, 10, mode=cv2.GC_INIT_WITH_MASK)
        output = cv.CreateImageHeader((mask_in.shape[1], mask_in.shape[0]), cv.IPL_DEPTH_8U, 1)
        cv.SetData(output, mask_in.tostring(), (mask_in.dtype.itemsize * mask_in.shape[1]))
        LUT = np.zeros((256, 1), dtype=uint8)
        LUT[1] = 255
        LUT[2] = 64
        LUT[3] = 192
        cv.LUT(output, output, cv.fromarray(LUT))
        mask._graybitmap = None
        retVal = Image(output)
    elif (rect is not None):
        npimg = np.array(cv.GetMat(self.getBitmap()))
        tmp1 = np.zeros((1, (13 * 5)))
        tmp2 = np.zeros((1, (13 * 5)))
        mask = np.zeros((self.height, self.width), dtype='uint8')
        cv2.grabCut(npimg, mask, rect, tmp1, tmp2, 10, mode=cv2.GC_INIT_WITH_RECT)
        bmp = cv.CreateImageHeader((mask.shape[1], mask.shape[0]), cv.IPL_DEPTH_8U, 1)
        cv.SetData(bmp, mask.tostring(), (mask.dtype.itemsize * mask.shape[1]))
        LUT = np.zeros((256, 1), dtype=uint8)
        LUT[1] = 255
        LUT[2] = 64
        LUT[3] = 192
        cv.LUT(bmp, bmp, cv.fromarray(LUT))
        retVal = Image(bmp)
    else:
        logger.warning('ImageClass.findBlobsSmart    requires    either    a    mask    or    a    selection    rectangle.    Failure    to    provide    one    of    these    causes    your    bytes    to    splinter    and    bit    shrapnel    to    hit    your    pipeline    making    it    asplode    in    a    ball    of    fire.    Okay...    not    really')
    return retVal
