Mobile Development 8 min read

Extracting Car Outlines from Sample Images for 360° Vehicle Capture in an iOS App

This article describes a step‑by‑step iOS implementation that converts example car images into bitmap points, scans edges, removes duplicate points, compensates missing vertices, and finally builds a closed BezierPath to guide 360° vehicle photography, including full Objective‑C code snippets.

HomeTech
HomeTech
HomeTech
Extracting Car Outlines from Sample Images for 360° Vehicle Capture in an iOS App

Background – Users typically view cars online in a uniform way, so the team needed a method to let merchants capture 360° vehicle images at home. Simple example‑image guidance proved unreliable due to varying shooting distances and angles, prompting the development of an automated contour‑extraction and shooting‑assist component for the CarSmart+ app.

Implementation Idea – The process starts by converting the example image to bitmap points, then scanning from top, bottom, left, and right according to a known rule (non‑transparent pixels) to obtain four edge point arrays. These arrays are merged into an ordered set of points, which are then connected to form a closed BezierPath.

Problems Encountered – Directly merging the four edge arrays caused duplicate points and non‑continuous sequences, resulting in malformed shapes. The solution was to de‑duplicate the horizontal (left/right) and vertical (top/bottom) arrays separately, then use the vertical arrays to supplement the horizontal ones before final merging.

Final Implementation and Core Code

NSMutableArray<NSValue *> *arrLeft = [NSMutableArray array];
NSMutableArray<NSValue *> *arrBottom = [NSMutableArray array];
NSMutableArray<NSValue *> *arrRight = [NSMutableArray array];
NSMutableArray<NSValue *> *arrTop = [NSMutableArray array];

for (NSInteger row = 0; row < h; row++) {
    // left edge
    for (NSInteger col = 0; col < w; col++) {
        const uint8_t *pixel = &rgba[row * bytesPerRow + col * bytesPerPixel];
        if (pixel[3] != 0x00) { [arrLeft addObject:[NSValue valueWithCGPoint:CGPointMake(col, row)]]; break; }
    }
    // right edge
    for (NSInteger col = w - 1; col >= 0; col--) {
        const uint8_t *pixel = &rgba[row * bytesPerRow + col * bytesPerPixel];
        if (pixel[3] != 0x00) { [arrRight insertObject:[NSValue valueWithCGPoint:CGPointMake(col, row)] atIndex:0]; break; }
    }
}

for (NSInteger col = 0; col < w; col++) {
    // bottom edge
    for (NSInteger row = h - 1; row >= 0; row--) {
        const uint8_t *pixel = &rgba[row * bytesPerRow + col * bytesPerPixel];
        if (pixel[3] != 0x00) { [arrBottom addObject:[NSValue valueWithCGPoint:CGPointMake(col, row)]]; break; }
    }
    // top edge
    for (NSInteger row = 0; row < h; row++) {
        const uint8_t *pixel = &rgba[row * bytesPerRow + col * bytesPerPixel];
        if (pixel[3] != 0x00) { [arrTop insertObject:[NSValue valueWithCGPoint:CGPointMake(col, row)] atIndex:0]; break; }
    }
}
NSMutableSet *arrLeftSet = [NSMutableSet setWithArray:arrLeft];
NSMutableSet *arrRightSet = [NSMutableSet setWithArray:arrRight];
NSMutableSet *arrBottomSet = [NSMutableSet setWithArray:arrBottom];
NSMutableSet *arrTopSet = [NSMutableSet setWithArray:arrTop];

[arrLeftSet intersectSet:arrRightSet];
for (int i = (int)(arrRight.count - 1); i >= 0; i--) {
    @autoreleasepool { NSValue *value = arrRight[i]; if ([arrLeftSet containsObject:value]) [arrRight removeObject:value]; }
}

[arrBottomSet intersectSet:arrTopSet];
for (int i = (int)(arrTop.count - 1); i >= 0; i--) {
    @autoreleasepool { NSValue *value = arrTop[i]; if ([arrBottomSet containsObject:value]) [arrTop removeObject:value]; }
}
// arrFixPoints is the top or bottom edge array
NSMutableSet<NSValue *> *arrCoincidentPointsSet = [NSMutableSet setWithArray:arrFixPoints];
// arrOriginalPoints is the left or right edge array
[arrCoincidentPointsSet intersectSet:[NSSet setWithArray:arrOriginalPoints]];

Effect Demonstration – The resulting BezierPath accurately outlines the vehicle, as shown in the before‑and‑after screenshots, improving both shooting efficiency and quality for merchants.

Conclusion – While many contour‑extraction methods exist (OpenCV, Vision, DeepLab), the specific constraints of the sample images allowed a lightweight, rule‑based solution without external libraries. Future work may explore more robust or AI‑driven approaches.

mobile developmentiOSimage processingObjective-CBezierPathContour Detection
HomeTech
Written by

HomeTech

HomeTech tech sharing

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.