目录

Card Recognition

Since 6.1.1(24), recognition of the Mainland Travel Permit for Hong Kong and Macao Residents and Mainland Travel Permit for Taiwan Residents has been added.

Use Cases

The card recognition control provides structured recognition services for ID cards, vehicle licenses, driver's licenses, passports, bank cards, Mainland Travel Permits for Hong Kong and Macao Residents, and Mainland Travel Permits for Taiwan Residents. Please note that ID card support is currently limited to Chinese second-generation ID cards (excluding Hong Kong SAR, Macao SAR, and Taiwan, China) and excludes bilingual (Han and ethnic minority languages) versions. With the built-in automatic classification feature, the system can automatically identify the card type and return both structured data and card image information.

In scenarios where the information about a certificate (such as an ID card or bank card) needs to be filled in, the card recognition control can be used to read the Optical Character Recognition (OCR) information and return the result. The front and back sides can be identified separately, or both sides can be identified at the same time.

Figure 1 Bank card recognition

Constraints

API Description

The following lists only some main APIs called in the demo. For details about all APIs, please refer to the API Reference.

API Description
CardRecognition Card recognition control
CardRecognitionResult Card recognition result.

Development Procedure

  1. Add classes related to the card recognition control to a project.

    import { CardRecognition, CardRecognitionResult, CardType, CardSide, CardRecognitionConfig, ShootingMode, CardContentConfig, BankCardConfig } from '@kit.VisionKit';
    import { hilog } from '@kit.PerformanceAnalysisKit';
  2. Configure a UI layout, select the types and sides of cards to be recognized, set related parameters, and obtain return values through callbacks.

    Since 5.1.1(19), the callback parameter in the CardRecognition API has been deprecated. Use onResult instead.

    The following are code examples for recognizing ID cards, bank cards, passports, driver's licenses, vehicle licenses, Mainland Travel Permits for Hong Kong and Macao Residents, and Mainland Travel Permits for Taiwan Residents.

    const TAG = 'CardRecognition';
    
    @Entry
    @Component
    struct Index {
      build() {
        Column() {
          // Identity Card
          CardRecognition({
            supportType: CardType.CARD_ID,
            // ID cards can be recognized on both sides.
            cardSide: CardSide.DEFAULT,
            cardRecognitionConfig: {
              defaultShootingMode: ShootingMode.MANUAL,
              isPhotoSelectionSupported: true
            },
            onResult: ((params: CardRecognitionResult) => {
              hilog.info(0x0001, TAG, `params code: ${params.code}`);
              hilog.info(0x0001, TAG, `params cardType: ${params.cardType}`);
              hilog.info(0x0001, TAG, `params cardInfo front: ${JSON.stringify(params.cardInfo?.front)}`);
              hilog.info(0x0001, TAG, `params cardInfo back: ${JSON.stringify(params.cardInfo?.back)}`);
            })
          })
        }
        .height('100%')
        .width('100%')
      }
    }
    const TAG = 'CardRecognition';
    
    @Entry
    @Component
    struct Index {
      build() {
        Column() {
          // Bank card.
          CardRecognition({
            supportType: CardType.CARD_BANK,
            // One side of a bank card can be recognized.
            cardSide: CardSide.FRONT,
            cardRecognitionConfig: {
              defaultShootingMode: ShootingMode.MANUAL,
              isPhotoSelectionSupported: true,
              cardContentConfig: { bankCard: { isBankNumberDialogShown: true} }
            },
            onResult: ((params: CardRecognitionResult) => {
              hilog.info(0x0001, TAG, `params code: ${params.code}`);
              hilog.info(0x0001, TAG, `params cardType: ${params.cardType}`);
              hilog.info(0x0001, TAG, `params cardInfo: ${JSON.stringify(params.cardInfo?.main)}`);
            })})
        }
        .height('100%')
        .width('100%')
      }
    }
    const TAG = 'CardRecognition';
    
    @Entry
    @Component
    struct Index {
      build() {
        Column() {
          // Passport
          CardRecognition({
            supportType: CardType.CARD_PASSPORT,
            // One side of a passport can be recognized.
            cardSide: CardSide.FRONT,
            cardRecognitionConfig: {
              defaultShootingMode: ShootingMode.MANUAL,
              isPhotoSelectionSupported: true
            },
            onResult: ((params: CardRecognitionResult) => {
              hilog.info(0x0001, TAG, `params code: ${params.code}`);
              hilog.info(0x0001, TAG, `params cardType: ${params.cardType}`);
              hilog.info(0x0001, TAG, `params cardInfo: ${JSON.stringify(params.cardInfo?.main)}`);
            })})
        }
        .height('100%')
        .width('100%')
      }
    }
    const TAG = 'CardRecognition';
    
    @Entry
    @Component
    struct Index {
      build() {
        Column() {
          // Driver's license.
          CardRecognition({
            supportType: CardType.CARD_DRIVER_LICENSE,
            // Both sides of a driver's license can be recognized.
            cardSide: CardSide.DEFAULT,
            cardRecognitionConfig: {
              defaultShootingMode: ShootingMode.MANUAL,
              isPhotoSelectionSupported: true
            },
            onResult: ((params: CardRecognitionResult) => {
              hilog.info(0x0001, TAG, `params code: ${params.code}`);
              hilog.info(0x0001, TAG, `params cardType: ${params.cardType}`);
              hilog.info(0x0001, TAG, `params cardInfo front: ${JSON.stringify(params.cardInfo?.front)}`);
              hilog.info(0x0001, TAG, `params cardInfo back: ${JSON.stringify(params.cardInfo?.back)}`);
            })
          })
        }
        .height('100%')
        .width('100%')
      }
    }
    const TAG = 'CardRecognition';
    
    @Entry
    @Component
    struct Index {
      build() {
        Column() {
          // Vehicle license
          CardRecognition({
            supportType: CardType.CARD_VEHICLE_LICENSE,
            // Both sides of a vehicle license can be recognized.
            cardSide: CardSide.DEFAULT,
            cardRecognitionConfig: {
              defaultShootingMode: ShootingMode.MANUAL,
              isPhotoSelectionSupported: true
            },
            onResult: ((params: CardRecognitionResult) => {
              hilog.info(0x0001, TAG, `params code: ${params.code}`);
              hilog.info(0x0001, TAG, `params cardType: ${params.cardType}`);
              hilog.info(0x0001, TAG, `params cardInfo front: ${JSON.stringify(params.cardInfo?.front)}`);
              hilog.info(0x0001, TAG, `params cardInfo back: ${JSON.stringify(params.cardInfo?.back)}`);
            })
          })
        }
        .height('100%')
        .width('100%')
      }
    }
    const TAG = 'CardRecognition';
    
    @Entry
    @Component
    struct Index {
      build() {
        Column() {
          // Mainland Travel Permit for Hong Kong and Macao Residents
          CardRecognition({
            supportType: CardType.CARD_MAINLAND_TRAVEL_PERMIT_HK_MO,
            // Both sides of the Mainland Travel Permit for Hong Kong and Macao Residents can be recognized.
            cardSide: CardSide.DEFAULT,
            cardRecognitionConfig: {
              defaultShootingMode: ShootingMode.MANUAL,
              isPhotoSelectionSupported: true
            },
            onResult: ((params: CardRecognitionResult) => {
              hilog.info(0x0001, TAG, `params code: ${params.code}`);
              hilog.info(0x0001, TAG, `params cardType: ${params.cardType}`);
              hilog.info(0x0001, TAG, `params cardInfo front: ${JSON.stringify(params.cardInfo?.front)}`);
              hilog.info(0x0001, TAG, `params cardInfo back: ${JSON.stringify(params.cardInfo?.back)}`);
            })
          })
        }
        .height('100%')
        .width('100%')
      }
    }
    const TAG = 'CardRecognition';
    
    @Entry
    @Component
    struct Index {
      build() {
        Column() {
          // Mainland Travel Permit for Taiwan Residents
          CardRecognition({
            supportType: CardType.CARD_MAINLAND_TRAVEL_PERMIT_TW,
            // Both sides of the Mainland Travel Permit for Taiwan Residents can be recognized.
            cardSide: CardSide.DEFAULT,
            cardRecognitionConfig: {
              defaultShootingMode: ShootingMode.MANUAL,
              isPhotoSelectionSupported: true
            },
            onResult: ((params: CardRecognitionResult) => {
              hilog.info(0x0001, TAG, `params code: ${params.code}`);
              hilog.info(0x0001, TAG, `params cardType: ${params.cardType}`);
              hilog.info(0x0001, TAG, `params cardInfo front: ${JSON.stringify(params.cardInfo?.front)}`);
              hilog.info(0x0001, TAG, `params cardInfo back: ${JSON.stringify(params.cardInfo?.back)}`);
            })
          })
        }
        .height('100%')
        .width('100%')
      }
    }

Development Example

[h2]Index.ets

// The development example of card recognition is implemented on two screens. One is the entry screen, and the other is the implementation screen.
// The entry screen needs to introduce the implementation screen. In the following example, the implementation screen file name is CardDemoPage.
import { CardDemoPage } from './CardDemoPage';

@Entry
@Component
struct MainPage {
  @Provide('pathStack') pathStack: NavPathStack = new NavPathStack();

  @Builder
  PageMap(name: string) {
    if (name === 'cardRecognition') {
      CardDemoPage()
    }
  }

  // Button on the card recognition entry screen.
  build() {
    Navigation(this.pathStack) {
      Button('CardRecognition', { stateEffect: true, type: ButtonType.Capsule })
        .width('50%')
        .height(40)
        .onClick(() => {
          this.pathStack.pushPath({ name: 'cardRecognition' });
        })
    }.title('Card recognition control demo').navDestination(this.PageMap)
    .mode(NavigationMode.Stack)
  }
}

[h2]CardDemoPage.ets

// Card recognition implementation screen, and its file name is **CardDemoPage**. This screen needs to be introduced by the entry screen.
import { CardRecognition, CardRecognitionResult, CardType, CardSide, ShootingMode } from '@kit.VisionKit';
import { hilog } from '@kit.PerformanceAnalysisKit';

const TAG: string = 'CardRecognitionPage';

// Card recognition screen, which is used to load uiExtensionAbility.
@Component
export struct CardDemoPage {
  @State cardDataSource: Record<string, string>[] = [];
  @Consume('pathStack') pathStack: NavPathStack;

  build() {
    NavDestination() {
      Stack({ alignContent: Alignment.Top }) {
        Stack() {
          this.cardDataShowBuilder()
        }
        .width('80%')
        .height('80%')

        CardRecognition({
          // Here, the ID card type is used as an example.
          supportType: CardType.CARD_ID,
          cardSide: CardSide.DEFAULT,
          cardRecognitionConfig: {
            defaultShootingMode: ShootingMode.MANUAL,
            isPhotoSelectionSupported: true
          },
          onResult: ((params: CardRecognitionResult) => {
            hilog.info(0x0001, TAG, `params code: ${params.code}`);
            if (params.code !== 200) {
              this.pathStack.pop();
            }
            hilog.info(0x0001, TAG, `params cardType: ${params.cardType}`);
            if (params.cardInfo?.front !== undefined) {
              this.cardDataSource.push(params.cardInfo?.front);
            }

            if (params.cardInfo?.back !== undefined) {
              this.cardDataSource.push(params.cardInfo?.back);
            }

            if (params.cardInfo?.main !== undefined) {
              this.cardDataSource.push(params.cardInfo?.main);
            }
            hilog.info(0x0001, TAG, `params cardInfo front: ${JSON.stringify(params.cardInfo?.front)}`);
            hilog.info(0x0001, TAG, `params cardInfo back: ${JSON.stringify(params.cardInfo?.back)}`);
          })
        })
      }
      .width('100%')
      .height('100%')
    }
    .width('100%')
    .height('100%')
    .hideTitleBar(true)
  }

  @Builder
  cardDataShowBuilder() {
    List() {
      ForEach(this.cardDataSource, (cardData: Record<string, string>) => {
        ListItem() {
          Column() {
            Image(cardData.cardImageUri)
              .objectFit(ImageFit.Contain)
              .width(100)
              .height(100)

            Text(JSON.stringify(cardData))
              .width('100%')
              .fontSize(12)
          }
        }
      })
    }
    .listDirection(Axis.Vertical)
    .alignListItem(ListItemAlign.Center)
    .margin({
      top: 50
    })
    .width('100%')
    .height('100%')
  }
}