Runs a CC analysis on the image_pix mask image, and creates image partitions from them, cutting out strong text, and merging with nearby image regions such that they don't interfere with text. Rotation and rerotation specify how to rotate image coords to match the blob and partition coords and back again. The input/output part_grid owns all the created partitions, and the partitions own all the fa
| 1282 | // ColPartitionGrid::ReTypeBlobs must be called afterwards to fix this |
| 1283 | // situation and collect the image blobs. |
| 1284 | void ImageFind::FindImagePartitions(Pix* image_pix, |
| 1285 | const FCOORD& rotation, |
| 1286 | const FCOORD& rerotation, |
| 1287 | TO_BLOCK* block, |
| 1288 | TabFind* tab_grid, |
| 1289 | ColPartitionGrid* part_grid, |
| 1290 | ColPartition_LIST* big_parts) { |
| 1291 | int imageheight = pixGetHeight(image_pix); |
| 1292 | Boxa* boxa; |
| 1293 | Pixa* pixa; |
| 1294 | ConnCompAndRectangularize(image_pix, &boxa, &pixa); |
| 1295 | // Iterate the connected components in the image regions mask. |
| 1296 | int nboxes = boxaGetCount(boxa); |
| 1297 | for (int i = 0; i < nboxes; ++i) { |
| 1298 | l_int32 x, y, width, height; |
| 1299 | boxaGetBoxGeometry(boxa, i, &x, &y, &width, &height); |
| 1300 | Pix* pix = pixaGetPix(pixa, i, L_CLONE); |
| 1301 | TBOX im_box(x, imageheight -y - height, x + width, imageheight - y); |
| 1302 | im_box.rotate(rotation); // Now matches all partitions and blobs. |
| 1303 | ColPartitionGridSearch rectsearch(part_grid); |
| 1304 | rectsearch.SetUniqueMode(true); |
| 1305 | ColPartition_LIST part_list; |
| 1306 | DivideImageIntoParts(im_box, rotation, rerotation, pix, |
| 1307 | &rectsearch, &part_list); |
| 1308 | if (textord_tabfind_show_images) { |
| 1309 | pixWrite("junkimagecomponent.png", pix, IFF_PNG); |
| 1310 | tprintf("Component has %d parts\n", part_list.length()); |
| 1311 | } |
| 1312 | pixDestroy(&pix); |
| 1313 | if (!part_list.empty()) { |
| 1314 | ColPartition_IT part_it(&part_list); |
| 1315 | if (part_list.singleton()) { |
| 1316 | // We didn't have to chop it into a polygon to fit around text, so |
| 1317 | // try expanding it to merge fragmented image parts, as long as it |
| 1318 | // doesn't touch strong text. |
| 1319 | ColPartition* part = part_it.extract(); |
| 1320 | TBOX text_box(im_box); |
| 1321 | MaximalImageBoundingBox(part_grid, &text_box); |
| 1322 | while (ExpandImageIntoParts(text_box, &rectsearch, part_grid, &part)); |
| 1323 | part_it.set_to_list(&part_list); |
| 1324 | part_it.add_after_then_move(part); |
| 1325 | im_box = part->bounding_box(); |
| 1326 | } |
| 1327 | EliminateWeakParts(im_box, part_grid, big_parts, &part_list); |
| 1328 | // Iterate the part_list and put the parts into the grid. |
| 1329 | for (part_it.move_to_first(); !part_it.empty(); part_it.forward()) { |
| 1330 | ColPartition* image_part = part_it.extract(); |
| 1331 | im_box = image_part->bounding_box(); |
| 1332 | part_grid->InsertBBox(true, true, image_part); |
| 1333 | if (!part_it.at_last()) { |
| 1334 | ColPartition* neighbour = part_it.data_relative(1); |
| 1335 | image_part->AddPartner(false, neighbour); |
| 1336 | neighbour->AddPartner(true, image_part); |
| 1337 | } |
| 1338 | } |
| 1339 | } |
| 1340 | } |
| 1341 | boxaDestroy(&boxa); |
nothing calls this directly
no test coverage detected