EXOBJ_OPTIONS (original) (raw)
Summary
Provides the options for extracting the objects.
Syntax
Members
L_UINT64 uStructSize
Size of this structure in bytes, for versioning. Use the sizeof(EXOBJ_OPTIONS) operator to calculate this value.
L_UINT uFlags
Flags must be a combination of the following values:
Value | Meaning |
---|---|
EXOBJ_8_CONNECTIVITY | [0x0001] Pass to enable 8-way connectivity (diagonals), otherwise 4-way (only NSEW) |
EXOBJ_OUTLINE | [0x0002] Extract pixels along each object's outline |
EXOBJ_DETECT_CHILDREN | [0x0004] Detect the children for each object, and output as a tree of nested objects |
EXOBJ_REPORT_IGNORED | [0x0008] Return ignored noise/containers in their respective lists |
EXOBJ_IGNORE_SMALL_NOISE | [0x0010] Ignore small noise during extraction (refer to nSmallNoiseThreshold) |
EXOBJ_IGNORE_LARGE_NOISE | [0x0020] Ignore large noise during extraction (refer to nLargeNoiseThreshold) |
EXOBJ_IGNORE_CONTAINERS | [0x0040] (Requires EXOBJ_DETECT_CHILDREN) Ignore containers during extraction (refer to uContainerMinCount) |
EXOBJ_CHECK_CONTAINER_SUBCHILDREN | [0x0080] (Requires EXOBJ_IGNORE_CONTAINERS) Check the number of children in a container by recursing to lower objects (not just immediate children) |
EXOBJ_CHECK_FOR_TABLES | [0x0100] (Requires EXOBJ_CHECK_CONTAINER_SUBCHILDREN) When filtering out a container, attempt to preserve the cell containers as children (refer to dTableMaxBorderPercent) |
EXOBJ_USE_MULTICOLORS | [0x0200] Extract objects for each specified color level (instead of just 1 BPP) |
EXOBJ_SORT_TOPLEFT | [0x0400] Sort the object lists in each EXOBJ_RESULT structure (sub-lists not sorted) |
EXOBJ_FLATTEN | [0x0800] (Requires EXOBJ_DETECT_CHILDREN) Flatten the final lists to store the children of an object immediately after the parent, rather than in a tree structure. |
L_RECT * pROI
Optional region of interest for extraction.
L_INT nSmallNoiseThreshold
The maximum pixel size of noise that will be considered too small.
L_INT nLargeNoiseThreshold
The minimum pixel size of noise that will be considered too large.
L_UINT uContainerMinCount
The minimum number of sub-objects within a container before ignoring.
L_DOUBLE dTableMaxBorderPercent
The maximum percentage of black pixels (estimated by the area of bounding rectangles) for a container to be considered a table.
L_INT nTableSizeThreshold
The minimum pixel size for a container to be considered a table.
EXOBJ_COLORINFO * pColorInfo
Optional array of color information structures.
L_UINT uColorInfoCount
The number of items in pColorInfo.
L_INT nMaxObjectCount
The maximum number of objects to return (or 0 for all objects).
Comments
If EXOBJ_IGNORE_LARGE_NOISE
and EXOBJ_IGNORE_SMALL_NOISE
are both specified, iSmallNoiseThreshold
must be smaller than iLargeNoiseThreshold
.
If EXOBJ_USE_MULTICOLORS
is specified, pColorInfo
is NULL, and uColorInfoCount
is 0, then the colors are pulled from BITMAPHANDLE.pPalette.
EXOBJ_SORT_TOPLEFT
is applied after EXOBJ_FLATTEN
and will remove the parent-child ordering in the final lists.
Containers (even if ignored) and sub-children will count towards the iMaxObjectCount
threshold, while small/large noise will not.
Usage
Example
This example shows how to perform multi-color extraction using L_ExtractObjectsBitmap.
L_INT ExObjOptionsExample(L_VOID)
{
L_INT nRet = SUCCESS;
BITMAPHANDLE InputBitmap = { 0 };
BITMAPHANDLE OutputBitmap = { 0 };
pEXOBJ_DATA pData = NULL;
EXOBJ_OPTIONS ExtractOptions = { 0 };
EXOBJ_COLORINFO ColorInfo[3] = { 0 };
L_TCHAR ColorNames[3][20] = { 0 };
EXOBJ_REGION_OPTIONS RegionOptions = { 0 };
pEXOBJ_OBJECT* pObjectArray = NULL; // Temporary array for L_ExtractObjects_CalcRegion
L_UINT uObjectArrayCount = 0;
// Load the original image
nRet = L_LoadBitmap(MAKE_IMAGE_PATH(TEXT("unwarp1.jpg")), &InputBitmap, sizeof(BITMAPHANDLE), 0, ORDER_BGRORGRAY, NULL, NULL);
if (nRet != SUCCESS)
goto cleanup;
// Setup the extraction options
ExtractOptions.uStructSize = sizeof(EXOBJ_OPTIONS);
ExtractOptions.uFlags = EXOBJ_8_CONNECTIVITY | EXOBJ_DETECT_CHILDREN | EXOBJ_OUTLINE | EXOBJ_IGNORE_SMALL_NOISE | EXOBJ_USE_MULTICOLORS;
ExtractOptions.nSmallNoiseThreshold = 5; // Filter out noise smaller than 5x5 pixels
ColorInfo[0].uStructSize = ColorInfo[1].uStructSize = ColorInfo[2].uStructSize = sizeof(EXOBJ_COLORINFO);
ColorInfo[0].uThreshold = ColorInfo[1].uThreshold = ColorInfo[2].uThreshold = 50;
strcpy_s(ColorNames[0], TEXT("DarkGray"));
ColorInfo[0].crColor = RGB(30, 30, 30);
strcpy_s(ColorNames[1], TEXT("DarkGreen"));
ColorInfo[1].crColor = RGB(41, 108, 70);
strcpy_s(ColorNames[2], TEXT("LightRed"));
ColorInfo[2].crColor = RGB(200, 68, 65);
ExtractOptions.pColorInfo = ColorInfo;
ExtractOptions.uColorInfoCount = 3;
// Extract the objects
nRet = L_ExtractObjectsBitmap(&InputBitmap, &ExtractOptions, &pData);
if (nRet != SUCCESS)
goto cleanup;
// Determine the total number of objects (braces for scope)
{
pEXOBJ_RESULT pResultIter;
for (pResultIter = pData->pHead, uObjectArrayCount = 0; pResultIter != NULL; pResultIter = pResultIter->pNext)
{
uObjectArrayCount += pResultIter->pObjects->uCount;
}
}
// Allocate a new array to hold the objects
pObjectArray = (pEXOBJ_OBJECT*)malloc(uObjectArrayCount * sizeof(pEXOBJ_OBJECT));
if (pObjectArray == NULL)
{
nRet = ERROR_NO_MEMORY;
goto cleanup;
}
// Convert the linked list to an array (braces for scope)
{
pEXOBJ_RESULT pResultIter;
L_INT nIndex;
for (pResultIter = pData->pHead, nIndex = 0; pResultIter != NULL; pResultIter = pResultIter->pNext)
{
pEXOBJ_OBJECT pObjectIter;
for (pObjectIter = pResultIter->pObjects->pHead; pObjectIter != NULL; pObjectIter = pObjectIter->pNext, nIndex++)
pObjectArray[nIndex] = pObjectIter;
}
}
// Setup the region options
RegionOptions.uStructSize = sizeof(EXOBJ_REGION_OPTIONS);
RegionOptions.uFlags = EXOBJ_REGION_HORIZONTAL;
// Calculate each object's region
nRet = L_ExtractObjects_CalcRegion(pData, pObjectArray, uObjectArrayCount, &RegionOptions);
if (nRet != SUCCESS)
goto cleanup;
// Create an output image
nRet = L_CreateBitmap(&OutputBitmap, sizeof(BITMAPHANDLE), TYPE_CONV, InputBitmap.Width, InputBitmap.Height, 24, ORDER_BGR, NULL, TOP_LEFT, NULL, 0);
if (nRet != SUCCESS)
goto cleanup;
// Extract each color to a separate image (braces for scope)
{
pEXOBJ_RESULT pResultIter;
EXOBJ_COLORINFO* pColorIter;
L_INT nNameIndex;
for (pResultIter = pData->pHead, pColorIter = ColorInfo, nNameIndex = 0; pResultIter != NULL; pResultIter = pResultIter->pNext, pColorIter++, nNameIndex++)
{
// Fill the output image with white
nRet = L_FillBitmap(&OutputBitmap, RGB(255, 255, 255));
if (nRet != SUCCESS)
goto cleanup;
// Populate the output image with each object's region (braces for scope)
{
pEXOBJ_OBJECT pObjectIter;
for (pObjectIter = pResultIter->pObjects->pHead; pObjectIter != NULL; pObjectIter = pObjectIter->pNext)
{
pEXOBJ_SEGMENT pSegmentIter;
for (pSegmentIter = pObjectIter->pRegionHorizontal->pHead; pSegmentIter != NULL; pSegmentIter = pSegmentIter->pNext)
{
// Update the region to the current segment
nRet = L_SetBitmapRgnRect(&OutputBitmap, NULL, &pSegmentIter->rcBounds, L_RGN_SET);
if (nRet != SUCCESS)
goto cleanup;
// Fill the region with the current color
nRet = L_FillBitmap(&OutputBitmap, pColorIter->crColor);
if (nRet != SUCCESS)
goto cleanup;
}
}
}
// Clear the output image's region
nRet = L_FreeBitmapRgn(&OutputBitmap);
if (nRet != SUCCESS)
goto cleanup;
// Save the output image (braces for scope)
{
L_TCHAR szOutputFile[MAX_PATH] = { 0 };
sprintf_s(szOutputFile, MAKE_IMAGE_PATH(TEXT("ExtractObjectsMultiColors_%s.png")), ColorNames[nNameIndex]);
nRet = L_SaveBitmap(szOutputFile, &OutputBitmap, FILE_PNG, 0, 0, NULL);
if (nRet != SUCCESS)
goto cleanup;
}
}
}
cleanup:
// Free the loaded images
if (InputBitmap.Flags.Allocated)
L_FreeBitmap(&InputBitmap);
if (OutputBitmap.Flags.Allocated)
L_FreeBitmap(&OutputBitmap);
// Free the results
if (pData != NULL)
L_ExtractObjects_FreeData(&pData);
// Free the array
if (pObjectArray != NULL)
free(pObjectArray);
return nRet;
}