int ColorLUT::growRegion(RectA *result, const Frame8 &frame, const Point16 &seed)
{
    uint8_t dir;
    Fpoint mean0, newMean;
    float dist;
    RectA newRegion, region;
    uint8_t done;

    m_hpixels = (HuePixel *)maxMalloc(sizeof(HuePixel)*CL_HPIXEL_MAX_SIZE, &m_hpixelSize);
    if (m_hpixels==NULL)
        return -1; // not enough memory

    m_hpixelSize /= sizeof(HuePixel);

    // create seed 2*GROW_INCx2*GROW_INC region from seed position, make sure it's within the frame
    region.m_xOffset = seed.m_x>GROW_INC ? seed.m_x-GROW_INC : 0;
    region.m_yOffset = seed.m_y>GROW_INC ? seed.m_y-GROW_INC : 0;
    region.m_width = 2*GROW_INC;
    if (region.m_xOffset+region.m_width>frame.m_width)
        region.m_width = frame.m_width-region.m_xOffset;
    region.m_height = 2*GROW_INC;
    if (region.m_yOffset+region.m_height>frame.m_height)
        region.m_height = frame.m_height-region.m_yOffset;

    map(frame, region);
    mean(&mean0);
    done = 0x00;

    while (1)
    {
        for (dir=0; dir<4; dir++)
        {
            if (done&(1<<dir))
                continue;
            else if (dir==0) // add to left
            {
                if (region.m_xOffset>GROW_INC)
                    newRegion.m_xOffset = region.m_xOffset-GROW_INC;
                else
                {
                    newRegion.m_xOffset = 0;
                    done |= 1<<dir;
                }
                newRegion.m_yOffset = region.m_yOffset;
                newRegion.m_width = GROW_INC;
                newRegion.m_height = region.m_height;
            }
            else if (dir==1) // add to top
            {
                if (region.m_yOffset>GROW_INC)
                    newRegion.m_yOffset = region.m_yOffset-GROW_INC;
                else
                {
                    newRegion.m_yOffset = 0;
                    done |= 1<<dir;
                }
                newRegion.m_xOffset = region.m_xOffset;
                newRegion.m_width = region.m_width;
                newRegion.m_height = GROW_INC;
            }
            else if (dir==2) // add to right
            {
                if (region.m_xOffset+region.m_width+GROW_INC>frame.m_width)
                {
                    newRegion.m_width = frame.m_width-region.m_xOffset-region.m_width;
                    done |= 1<<dir;
                }
                else
                    newRegion.m_width = GROW_INC;
                newRegion.m_xOffset = region.m_xOffset+region.m_width;
                newRegion.m_yOffset = region.m_yOffset;
                newRegion.m_height = region.m_height;
            }
            else // dir==3, add to bottom
            {
                if (region.m_yOffset+region.m_height+GROW_INC>frame.m_height)
                {
                    newRegion.m_height = frame.m_height-region.m_yOffset-region.m_height;
                    done |= 1<<dir;
                }
                else
                    newRegion.m_height = GROW_INC;
                newRegion.m_xOffset = region.m_xOffset;
                newRegion.m_yOffset = region.m_yOffset+region.m_height;
                newRegion.m_width = region.m_width;
            }

            // calculate new region mean
            map(frame, newRegion);
            mean(&newMean);

            // test new region
            dist = distance(mean0, newMean);

            if (dist>GROW_MAX_DISTANCE || m_hpixelLen==0)
                done |= 1<<dir;
            else // new region passes, so add new region
            {
                if (newRegion.m_xOffset<region.m_xOffset)
                {
                    region.m_xOffset = newRegion.m_xOffset;
                    region.m_width += newRegion.m_width;

                }
                else if (newRegion.m_yOffset<region.m_yOffset)
                {
                    region.m_yOffset = newRegion.m_yOffset;
                    region.m_height += newRegion.m_height;

                }
                else if (newRegion.m_xOffset+newRegion.m_width>region.m_xOffset+region.m_width)
                    region.m_width += newRegion.m_width;
                else if (newRegion.m_yOffset+newRegion.m_height>region.m_yOffset+region.m_height)
                    region.m_height += newRegion.m_height;
            }
            if (done==0x0f) // finished!
            {
                *result = region;
				result->m_width = result->m_width*GROW_REGION_ATTEN;
				result->m_xOffset += result->m_width*(1.0f-GROW_REGION_ATTEN)/2;
				result->m_height = result->m_height*GROW_REGION_ATTEN;
				result->m_yOffset += result->m_height*(1.0f-GROW_REGION_ATTEN)/2;
                free(m_hpixels);
                return 0;
            }
        }
    }
}
int ColorLUT::generate(ColorModel *model, const Frame8 &frame, const RectA &region)
{
    Fpoint meanVal;
    float angle, pangle, pslope, meanSat;
    float yi, istep, s, xsat, sat;
    int result;

    m_hpixels = (HuePixel *)maxMalloc(sizeof(HuePixel)*CL_HPIXEL_MAX_SIZE, &m_hpixelSize);
    if (m_hpixels==NULL)
        return -1; // not enough memory

    m_hpixelSize /= sizeof(HuePixel);

    map(frame, region);
    mean(&meanVal);
    angle = atan2(meanVal.m_y, meanVal.m_x);
    Fpoint uvec(cos(angle), sin(angle));

    Line hueLine(tan(angle), 0.0);

    pangle = angle + PI/2; // perpendicular angle
    pslope = tan(pangle); // perpendicular slope
    Line pLine(pslope, meanVal.m_y - pslope*meanVal.m_x); // perpendicular line through mean

    // upper hue line
    istep = fabs(m_iterateStep/uvec.m_x);
    yi = iterate(hueLine, istep);
    yi += fabs(m_hueTol*yi); // extend
    model->m_hue[0].m_yi = yi;
    model->m_hue[0].m_slope = hueLine.m_slope;

    // lower hue line
    yi = iterate(hueLine, -istep);
    yi -= fabs(m_hueTol*yi); // extend
    model->m_hue[1].m_yi = yi;
    model->m_hue[1].m_slope = hueLine.m_slope;

    // inner sat line
    s = sign(uvec.m_y);
    istep = s*fabs(m_iterateStep/cos(pangle));
    yi = iterate(pLine, -istep);
    yi -= s*fabs(m_satTol*(yi-pLine.m_yi)); // extend
    xsat = yi/(hueLine.m_slope-pslope); // x value where inner sat line crosses hue line
    Fpoint minsatVec(xsat, xsat*hueLine.m_slope); // vector going to inner sat line
    sat = dot(uvec, minsatVec); // length of line
    meanSat = dot(uvec, meanVal);
    if (sat < m_minSat) // if it's too short, we need to extend
    {
        minsatVec.m_x = uvec.m_x*m_minSat;
        minsatVec.m_y = uvec.m_y*m_minSat;
        yi = minsatVec.m_y - pslope*minsatVec.m_x;
    }
    model->m_sat[0].m_yi = yi;
    model->m_sat[0].m_slope = pslope;

    // outer sat line
    yi = iterate(pLine, istep);
    yi += s*fabs(m_maxSatRatio*m_satTol*(yi-pLine.m_yi)); // extend
    model->m_sat[1].m_yi = yi;
    model->m_sat[1].m_slope = pslope;

    // swap if outer sat line is greater than inner sat line
    // Arbitrary convention, but we need it to be consistent to test membership (checkBounds)
    if (model->m_sat[1].m_yi>model->m_sat[0].m_yi)
    {
        Line tmp = model->m_sat[0];
        model->m_sat[0] = model->m_sat[1];
        model->m_sat[1] = tmp;
    }

    free(m_hpixels);

    // calculate goodness
    result = (meanSat-m_minSat)*100/64 + 10; // 64 because it's half of our range
    if (result<0)
        result = 0;
    if (result>100)
        result = 100;

    return result;
}
Exemple #3
0
int ColorLUT::growRegion(RectA *result, const Frame8 &frame, const Point16 &seed)
{
    uint8_t dir;
    Fpoint mean0, newMean;
    float dist;
    RectA newRegion, region;
    uint8_t done;

    m_hpixels = (HuePixel *)maxMalloc(sizeof(HuePixel)*CL_HPIXEL_MAX_SIZE, &m_hpixelSize);
    if (m_hpixels==NULL)
        return -1; // not enough memory

    m_hpixelSize /= sizeof(HuePixel);

    // create seed 2*GROW_INCx2*GROW_INC region from seed position, make sure it's within the frame
    region.m_xOffset = seed.m_x>GROW_INC ? seed.m_x-GROW_INC : 0;
    region.m_yOffset = seed.m_y>GROW_INC ? seed.m_y-GROW_INC : 0;
    region.m_width = 2*GROW_INC;
    if (region.m_xOffset+region.m_width>frame.m_width)
        region.m_width = frame.m_width-region.m_xOffset;
    region.m_height = 2*GROW_INC;
    if (region.m_yOffset+region.m_height>frame.m_height)
        region.m_height = frame.m_height-region.m_yOffset;

	//mm find u and v (hue?) values for the region
    map(frame, region); //map gets the u and v values for the region, given FRAME. it then saves the result in the m_hpixels, which is accessed by mean.
    mean(&mean0); //mm mean is defined above: it calculates the mean position of a region (?) on the u-v hue matrix and saves it in the input argument, which is a Fpoint (point in 2D, floating precision).
    done = 0x00;

    while (1)
    {
		//mm iterate over all 4 directions for growing algorithm:
        for (dir=0; dir<4; dir++)
        {
            if (done&(1<<dir))
                continue;
            else if (dir==0) // add to left
            {
                if (region.m_xOffset>GROW_INC)
                    newRegion.m_xOffset = region.m_xOffset-GROW_INC;
                else
                {
                    newRegion.m_xOffset = 0;
                    done |= 1<<dir;
                }
                newRegion.m_yOffset = region.m_yOffset;
                newRegion.m_width = GROW_INC;
                newRegion.m_height = region.m_height;
            }
            else if (dir==1) // add to top
            {
                if (region.m_yOffset>GROW_INC)
                    newRegion.m_yOffset = region.m_yOffset-GROW_INC;
                else
                {
                    newRegion.m_yOffset = 0;
                    done |= 1<<dir;
                }
                newRegion.m_xOffset = region.m_xOffset;
                newRegion.m_width = region.m_width;
                newRegion.m_height = GROW_INC;
            }
            else if (dir==2) // add to right
            {
                if (region.m_xOffset+region.m_width+GROW_INC>frame.m_width)
                {
                    newRegion.m_width = frame.m_width-region.m_xOffset-region.m_width;
                    done |= 1<<dir;
                }
                else
                    newRegion.m_width = GROW_INC;
                newRegion.m_xOffset = region.m_xOffset+region.m_width;
                newRegion.m_yOffset = region.m_yOffset;
                newRegion.m_height = region.m_height;
            }
            else // dir==3, add to bottom
            {
                if (region.m_yOffset+region.m_height+GROW_INC>frame.m_height)
                {
                    newRegion.m_height = frame.m_height-region.m_yOffset-region.m_height;
                    done |= 1<<dir;
                }
                else
                    newRegion.m_height = GROW_INC;
                newRegion.m_xOffset = region.m_xOffset;
                newRegion.m_yOffset = region.m_yOffset+region.m_height;
                newRegion.m_width = region.m_width;
            }

            // calculate new region mean
            map(frame, newRegion);
            mean(&newMean);

            // test new region
            dist = distance(mean0, newMean); //mm this distance is in color space, not pixel space!!!! if the distance is too large, then the region stops growing!! this is at least one of the moments when image data is compared to clut data, and it happens in distance!! THINK THIS TRHOUGH!
				//It doesn't happen directly in distance: Distance simply calculates the Euclidean norm between the input points. 

            if (dist>GROW_MAX_DISTANCE || m_hpixelLen==0)
                done |= 1<<dir;
            else // new region passes, so add new region
            {
                if (newRegion.m_xOffset<region.m_xOffset)
                {
                    region.m_xOffset = newRegion.m_xOffset;
                    region.m_width += newRegion.m_width;

                }
                else if (newRegion.m_yOffset<region.m_yOffset)
                {
                    region.m_yOffset = newRegion.m_yOffset;
                    region.m_height += newRegion.m_height;

                }
                else if (newRegion.m_xOffset+newRegion.m_width>region.m_xOffset+region.m_width)
                    region.m_width += newRegion.m_width;
                else if (newRegion.m_yOffset+newRegion.m_height>region.m_yOffset+region.m_height)
                    region.m_height += newRegion.m_height;
            }
            if (done==0x0f) // finished!
            {
                *result = region;
				result->m_width = result->m_width*GROW_REGION_ATTEN;
				result->m_xOffset += result->m_width*(1.0f-GROW_REGION_ATTEN)/2;
				result->m_height = result->m_height*GROW_REGION_ATTEN;
				result->m_yOffset += result->m_height*(1.0f-GROW_REGION_ATTEN)/2;
                free(m_hpixels);
                return 0;
            }
        }
    }
}