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 ®ion) { 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; }
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; } } } }