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; }