Writing an Android Sync Provider

http://www.c99.org/2010/01/23/writing-an-android-sync-provider-part-1/

http://www.c99.org/2010/01/23/writing-an-android-sync-provider-part-2/

 

One of the highlights of the Android 2.0 SDK is that you can write custom sync providers to integrate with the system contacts, calendars, etc. The only problem is that there’s very little documentation on how it all fits together. And worse, if you mess up in certain places, the Android system will crash and reboot! Always up for a challenge, I’ve navigated through the sparse documentation, vague mailing list posts, and the Android source code itself to build a sync provider for our Last.fm app. Want to know how to build your own? Read on!

Account Authenticators

The first piece of the puzzle is called an Account Authenticator , which defines how the user’s account will appear in the “Accounts & Sync” settings. Implementing an Account Authenticator requires 3 pieces: a service that returns a subclass of AbstractAccountAuthenticator from the onBind method, an activity to prompt the user to enter their credentials, and an xml file describing how your account should look when displayed to the user. You’ll also need to add the android.permission.AUTHENTICATE_ACCOUNTS permission to your AndroidManifest.xml.

The Service

The authenticator service is expected to return a subclass of AbstractAccountAuthenticator from the onBind method — if you don’t, Android will crash and reboot when you try to add a new account to the system. The only method in AbstractAccountAuthenticator we really need to implement is addAccount, which returns an Intent that the system will use to display the login dialog to the user. The implementation below will launch our app’s main launcher activity with an action of “fm.last.android.sync.LOGIN” and an extra containing the AccountAuthenticatorResponse object we use to pass data back to the system after the user has logged in.

AccountAuthenticatorService.java
  1. import fm.last.android.LastFm;
  2. import android.accounts.AbstractAccountAuthenticator;
  3. import android.accounts.Account;
  4. import android.accounts.AccountAuthenticatorResponse;
  5. import android.accounts.AccountManager;
  6. import android.accounts.NetworkErrorException;
  7. import android.app.Service;
  8. import android.content.Context;
  9. import android.content.Intent;
  10. import android.os.Bundle;
  11. import android.os.IBinder;
  12. import android.util.Log;
  13.  
  14. /**
  15.  * Authenticator service that returns a subclass of AbstractAccountAuthenticator in onBind()
  16.  */
  17. public class AccountAuthenticatorService extends Service {
  18.   private static final String TAG = "AccountAuthenticatorService" ;
  19.   private static AccountAuthenticatorImpl sAccountAuthenticator = null ;
  20.  
  21.   public AccountAuthenticatorService ( ) {
  22.   super ( ) ;
  23.   }
  24.  
  25.   public IBinder onBind ( Intent intent ) {
  26.   IBinder ret = null ;
  27.   if ( intent. getAction ( ) . equals ( android. accounts . AccountManager . ACTION_AUTHENTICATOR_INTENT ) )
  28.    ret = getAuthenticator ( ) . getIBinder ( ) ;
  29.   return ret ;
  30.   }
  31.  
  32.   private AccountAuthenticatorImpl getAuthenticator ( ) {
  33.   if ( sAccountAuthenticator == null )
  34.    sAccountAuthenticator = new AccountAuthenticatorImpl ( this ) ;
  35.   return sAccountAuthenticator ;
  36.   }
  37.  
  38.   private static class AccountAuthenticatorImpl extends AbstractAccountAuthenticator {
  39.   private Context mContext ;
  40.  
  41.   public AccountAuthenticatorImpl ( Context context ) {
  42.     super ( context ) ;
  43.    mContext = context ;
  44.   }
  45.  
  46.   /*
  47.    *  The user has requested to add a new account to the system.  We return an intent that will launch our login screen if the user has not logged in yet,
  48.    *  otherwise our activity will just pass the user's credentials on to the account manager.
  49.    */
  50.   @Override
  51.   public Bundle addAccount ( AccountAuthenticatorResponse response, String accountType, String authTokenType, String [ ] requiredFeatures, Bundle options )
  52.     throws NetworkErrorException {
  53.    Bundle reply = new Bundle ( ) ;
  54.    
  55.    Intent i = new Intent ( mContext, LastFm. class ) ;
  56.    i. setAction ( "fm.last.android.sync.LOGIN" ) ;
  57.    i. putExtra ( AccountManager. KEY_ACCOUNT_AUTHENTICATOR_RESPONSE , response ) ;
  58.    reply. putParcelable ( AccountManager. KEY_INTENT , i ) ;
  59.    
  60.     return reply ;
  61.   }
  62.  
  63.   @Override
  64.   public Bundle confirmCredentials ( AccountAuthenticatorResponse response, Account account, Bundle options ) {
  65.     return null ;
  66.   }
  67.  
  68.   @Override
  69.   public Bundle editProperties ( AccountAuthenticatorResponse response, String accountType ) {
  70.     return null ;
  71.   }
  72.  
  73.   @Override
  74.   public Bundle getAuthToken ( AccountAuthenticatorResponse response, Account account, String authTokenType, Bundle options ) throws NetworkErrorException {
  75.     return null ;
  76.   }
  77.  
  78.   @Override
  79.   public String getAuthTokenLabel ( String authTokenType ) {
  80.     return null ;
  81.   }
  82.  
  83.   @Override
  84.   public Bundle hasFeatures ( AccountAuthenticatorResponse response, Account account, String [ ] features ) throws NetworkErrorException {
  85.     return null ;
  86.   }
  87.  
  88.   @Override
  89.   public Bundle updateCredentials ( AccountAuthenticatorResponse response, Account account, String authTokenType, Bundle options ) {
  90.     return null ;
  91.   }
  92.   }
  93. }

The account authenticator service should be defined in your AndroidManifest.xml, with a meta-data tag referencing an xml definition file, as follows:

Snippet from AndroidManifest.xml
  1. <service android:name ="AccountAuthenticatorService"
  2.   android:exported = "true" android:process = ":auth" >
  3.   <intent-filter>
  4.   <action android:name ="android.accounts.AccountAuthenticator" />
  5.   </intent-filter>
  6.   <meta-data android:name ="android.accounts.AccountAuthenticator"
  7.   android:resource = "@xml/authenticator" />
  8. </service>

The Activity

If you don’t already have a login screen, there’s a convenience class AccountAuthenticatorActivity you can subclass that will pass your response back to the authentication manager for you, however if you already have a login activity in place you may find it easier to just pass the data back yourself, as I have done here. When the user has successfully been authenticated, we create an Account object for the user’s credentials. An account has an account name, such as the username or email address, and an account type, which you will define in your xml file next. You may find it easier to store your account type in strings.xml and use getString() to fetch it, as it is used in multiple places.

Snippet from the Last.fm login activity
  1. Account account = new Account ( username, getString ( R. string . ACCOUNT_TYPE ) ) ) ;
  2. AccountManager am = AccountManager. get ( this ) ;
  3. boolean accountCreated = am. addAccountExplicitly ( account, password, null ) ;
  4.  
  5. Bundle extras = getIntent. getExtras ( ) ;
  6. if ( extras ! = null ) {
  7.   if ( accountCreated ) {   //Pass the new account back to the account manager
  8.   AccountAuthenticatorResponse response = extras. getParcelable ( AccountManager. KEY_ACCOUNT_AUTHENTICATOR_RESPONSE ) ;
  9.   Bundle result = new Bundle ( ) ;
  10.   result. putString ( AccountManager. KEY_ACCOUNT_NAME , username ) ;
  11.   result. putString ( AccountManager. KEY_ACCOUNT_TYPE , getString ( R. string . ACCOUNT_TYPE ) ) ;
  12.   response. onResult ( result ) ;
  13.   }
  14.  finish ( ) ;
  15. }

The XML definition file

The account xml file defines what the user will see when they’re interacting with your account. It contains a user-readable name, the system account type you’re defining, various icons, and a reference to an xml file containing PreferenceScreens the user will see when modifying your account.

authenticator.xml
  1. <account-authenticator xmlns:android ="http://schemas.android.com/apk/res/android"
  2.     android:accountType = "fm.last.android.account"
  3.     android:icon = "@drawable/icon"
  4.     android:smallIcon = "@drawable/icon"
  5.     android:label = "@string/app_name"
  6.     android:accountPreferences = "@xml/account_preferences" />
account_preferences.xml
  1. <PreferenceScreen
  2.   xmlns:android = "http://schemas.android.com/apk/res/android" >
  3.     <PreferenceCategory
  4.             android:title = "General Settings" />
  5.  
  6.     <PreferenceScreen
  7.         android:key = "account_settings"
  8.         android:title = "Account Settings"
  9.         android:summary = "Sync frequency, notifications, etc." >
  10.         <intent
  11.             android:action = "fm.last.android.activity.Preferences.ACCOUNT_SETUP"
  12.             android:targetPackage = "fm.last.android"
  13.             android:targetClass = "fm.last.android.activity.Preferences" />
  14.     </PreferenceScreen>
  15. </PreferenceScreen>

Putting it all together

Now we’re ready for testing! The Android accounts setting screen doesn’t handle exceptions very well — if something goes wrong, your device will reboot! A better way to test is to launch the emulator, run the “Dev Tools” app, and pick “AccountsTester”.

You should see your new account type in the list, along with the built-in “Corporate” account type. Go ahead and select your account type from the drop-down list, and then press the “Add” button, and you should be presented with your login activity. After authenticating, your account should appear in a list below the buttons. At this point, it should be safe to use the system “Accounts & Sync” settings screen to remove or modify your account.

Ready to fill in that section below “Data & synchronization”? Let’s move on to part 2 !

The source code for the implementation referenced here is available in my Last.fm github project under the terms of the GNU General Public License. A standalone sample project is also available here under the terms of the Apache License 2.0. Google has also released their own sample sync provider on the Android developer portal that’s a bit more complete than mine.

 

One of the great new user-facing features of Android 2.0 is the is the new Facebook app, which brings your Facebook contacts and statuses into your Android contacts database:

So, how exactly does my Nexus One know that Chris is excited about the upcoming launch of his new mobile apps? The answer is a Contacts sync provider in the Facebook app. Read on to learn how to create your own!

Sync Providers

Sync providers are services that allow an Account to synchronize data on the device on a regular basis. Not quite sure how to create an Account? Read part one first! To implement a Contacts sync provider, we’ll need a service, some xml files, and the following permissions added to the AndroidManifest.xml:

AndroidManifest.xml snippet
  1. <uses-permission android:name ="android.permission.INTERNET" />
  2. <uses-permission android:name ="android.permission.ACCESS_NETWORK_STATE" />
  3. <uses-permission android:name ="android.permission.READ_CONTACTS" />
  4. <uses-permission android:name ="android.permission.WRITE_CONTACTS" />
  5. <uses-permission android:name ="android.permission.GET_ACCOUNTS" />
  6. <uses-permission android:name ="android.permission.MANAGE_ACCOUNTS" />
  7. <uses-permission android:name ="android.permission.AUTHENTICATE_ACCOUNTS" />
  8. <uses-permission android:name ="android.permission.READ_SYNC_SETTINGS" />
  9. <uses-permission android:name ="android.permission.WRITE_SYNC_SETTINGS" />

The Service

Similar to our Account Authenticator service, our Contacts Sync Provider service will return a subclass of AbstractThreadedSyncAdapter from the onBind method.

ContactsSyncAdapterService.java
  1. public class ContactsSyncAdapterService extends Service {
  2.   private static final String TAG = "ContactsSyncAdapterService" ;
  3.   private static SyncAdapterImpl sSyncAdapter = null ;
  4.   private static ContentResolver mContentResolver = null ;
  5.  
  6.   public ContactsSyncAdapterService ( ) {
  7.   super ( ) ;
  8.   }
  9.  
  10.   private static class SyncAdapterImpl extends AbstractThreadedSyncAdapter {
  11.   private Context mContext ;
  12.  
  13.   public SyncAdapterImpl ( Context context ) {
  14.     super ( context, true ) ;
  15.    mContext = context ;
  16.   }
  17.  
  18.   @Override
  19.   public void onPerformSync ( Account account, Bundle extras, String authority, ContentProviderClient provider, SyncResult syncResult ) {
  20.     try {
  21.     ContactsSyncAdapterService. performSync ( mContext, account, extras, authority, provider, syncResult ) ;
  22.     } catch ( OperationCanceledException e ) {
  23.     }
  24.   }
  25.   }
  26.  
  27.  @Override
  28.   public IBinder onBind ( Intent intent ) {
  29.   IBinder ret = null ;
  30.   ret = getSyncAdapter ( ) . getSyncAdapterBinder ( ) ;
  31.   return ret ;
  32.   }
  33.  
  34.   private SyncAdapterImpl getSyncAdapter ( ) {
  35.   if ( sSyncAdapter == null )
  36.    sSyncAdapter = new SyncAdapterImpl ( this ) ;
  37.   return sSyncAdapter ;
  38.   }
  39.  
  40.   private static void performSync ( Context context, Account account, Bundle extras, String authority, ContentProviderClient provider, SyncResult syncResult )
  41.     throws OperationCanceledException {
  42.   mContentResolver = context. getContentResolver ( ) ;
  43.   Log. i ( TAG, "performSync: " + account. toString ( ) ) ;
  44.   //This is where the magic will happen!
  45.   }
  46. }

The service is defined in AndroidManifest.xml like so:

AndroidManifest.xml snippet
  1. <service android:name =".sync.ContactsSyncAdapterService"
  2.   android:exported = "true" android:process = ":contacts" >
  3.   <intent-filter>
  4.   <action android:name ="android.content.SyncAdapter" />
  5.   </intent-filter>
  6.   <meta-data android:name ="android.content.SyncAdapter"
  7.   android:resource = "@xml/sync_contacts" />
  8. </service>

Finally, we need an xml file to let Android know that our sync provider handles Contacts for the Account type we defined in part 1.

sync_contacts.xml
  1. <sync-adapter xmlns:android ="http://schemas.android.com/apk/res/android"
  2.     android:contentAuthority = "com.android.contacts"
  3.     android:accountType = "fm.last.android.account" />

At this point we have a sync provider that doesn’t do anything, but also shouldn’t crash the Android system. Just in case, lets test it in Dev Tools first. Start the Android emulator and launch the “Dev Tools” app, then scroll down to “Sync Tester”.

The drop-down should confirm that com.android.contacts can be synced with the account type you’ve created. Select the entry for your account type and press the “Bind” button to connect to your sync service. If all goes well, Sync Tester will say it’s connected to your service. Now click “Start Sync” and select your account from the popup. Sync Tester will let you know that the sync succeeded (even though we didn’t actually do anything). At this point it should be safe to enable contact syncing from the Accounts & Sync settings screen without Android crashing and rebooting.

Contacts

Lets take a moment to discuss how Contacts on Android work. Each sync account, such as Google or Facebook, creates its own set of RawContacts which the Android system then aggregates into the single list of contacts you see in the Dialer. The RawContacts table contains several fields that Sync Providers can use for whatever they like, and in this implementation we will use the SYNC1 field to store the RawContact’s Last.fm username.

Contact Data

Data, such as name, phone number, email address, etc. is stored in a table that references a RawContact ID. The Data table can contain anything you like, and there are several predefined MIME-types available for phone numbers, email addresses, names, etc. Android will automatically try to combine RawContacts that contain the same name, email address, etc. into a single Contact, and the user can also combine and split Contacts manually from the contact edit screen.

Custom Data Types

A sync provider can store additional data about a RawContact in the Data table, and provide an xml file to tell the Contacts app how to format this row. To create a custom MIME type, we need to add an additional meta-data tag to our service entry in AndroidManifest.xml to reference a new ContactsSource XML file:

AndroidManifest.xml snippet
  1. <meta-data android:name ="android.provider.CONTACTS_STRUCTURE"
  2.   android:resource = "@xml/contacts" />

This ContactsSource xml file will tell the Contacts app how to format our custom MIME-types. In the example below, we specify an icon, and tell the Contacts app to use the DATA2 and DATA3 columns to render the fields. Note that this file’s format doesn’t appear to be documented outside of the source code for the Contacts app .

contacts.xml
  1. <ContactsSource xmlns:android ="http://schemas.android.com/apk/res/android" >
  2.   <ContactsDataKind
  3.   android:icon = "@drawable/icon"
  4.   android:mimeType = "vnd.android.cursor.item/vnd.fm.last.android.profile"
  5.   android:summaryColumn = "data2"
  6.   android:detailColumn = "data3"
  7.   android:detailSocialSummary = "true" />
  8. </ContactsSource>

Here’s how Facebook’s custom “Facebook Profile” field looks when rendered by the Contacts app:

Creating a RawContact

Now lets put all the above information together to create a RawContact for a Last.fm user. Our contacts will display only a name and a custom field that links to the user’s Last.fm profile. We store the user’s username in the RawContact’s SYNC1 field so we can easily look it up later. We will batch together the creation of the RawContact and the insertion of the Data, as Android will run an aggregation pass after each batch completes.

addContact method
  1. private static void addContact ( Account account, String name, String username ) {
  2.  Log. i ( TAG, "Adding contact: " + name ) ;
  3.  ArrayList < ContentProviderOperation > operationList = new ArrayList < ContentProviderOperation > ( ) ;
  4.  
  5.   //Create our RawContact
  6.  ContentProviderOperation. Builder builder = ContentProviderOperation. newInsert ( RawContacts. CONTENT_URI ) ;
  7.  builder. withValue ( RawContacts. ACCOUNT_NAME , account. name ) ;
  8.  builder. withValue ( RawContacts. ACCOUNT_TYPE , account. type ) ;
  9.  builder. withValue ( RawContacts. SYNC1 , username ) ;
  10.  operationList. add ( builder. build ( ) ) ;
  11.  
  12.   //Create a Data record of common type 'StructuredName' for our RawContact
  13.  builder = ContentProviderOperation. newInsert ( ContactsContract. Data . CONTENT_URI ) ;
  14.  builder. withValueBackReference ( ContactsContract. CommonDataKinds . StructuredName . RAW_CONTACT_ID , 0 ) ;
  15.  builder. withValue ( ContactsContract. Data . MIMETYPE , ContactsContract. CommonDataKinds . StructuredName . CONTENT_ITEM_TYPE ) ;
  16.  builder. withValue ( ContactsContract. CommonDataKinds . StructuredName . DISPLAY_NAME , name ) ;
  17.  operationList. add ( builder. build ( ) ) ;
  18.  
  19.   //Create a Data record of custom type "vnd.android.cursor.item/vnd.fm.last.android.profile" to display a link to the Last.fm profile
  20.  builder = ContentProviderOperation. newInsert ( ContactsContract. Data . CONTENT_URI ) ;
  21.  builder. withValueBackReference ( ContactsContract. Data . RAW_CONTACT_ID , 0 ) ;
  22.  builder. withValue ( ContactsContract. Data . MIMETYPE , "vnd.android.cursor.item/vnd.fm.last.android.profile" ) ;
  23.  builder. withValue ( ContactsContract. Data . DATA1 , username ) ;
  24.  builder. withValue ( ContactsContract. Data . DATA2 , "Last.fm Profile" ) ;
  25.  builder. withValue ( ContactsContract. Data . DATA3 , "View profile" ) ;
  26.  operationList. add ( builder. build ( ) ) ;
  27.  
  28.   try {
  29.   mContentResolver. applyBatch ( ContactsContract. AUTHORITY , operationList ) ;
  30.   } catch ( Exception e ) {
  31.   Log. e ( TAG, "Something went wrong during creation! " + e ) ;
  32.   e. printStackTrace ( ) ;
  33.   }
  34. }

Social status updates

Android keeps another table for social networking status updates. Inserting a record into this table will replace any previous status if the timestamp of the insert is newer than the previous timestamp, otherwise the previous record will remain and the new insert will be discarded. A status update record is associated with a Data record, in our implementation we will associate it with our Last.fm profile record. Status records contain the status text, a package name where resources are located, an icon resource, and a label resource. Below is a function that will insert a status update, as well as updating our Last.fm Profile Data record to display the last track the user listened to. Note that for efficiency purposes, we will send all the updates in a single batch, so Android will only run a single aggregation pass at the end.

updateContactStatus method
  1. private static void updateContactStatus ( ArrayList < ContentProviderOperation > operationList, long rawContactId, Track track ) {
  2.  Uri rawContactUri = ContentUris. withAppendedId ( RawContacts. CONTENT_URI , rawContactId ) ;
  3.  Uri entityUri = Uri. withAppendedPath ( rawContactUri, Entity . CONTENT_DIRECTORY ) ;
  4.   Cursor c = mContentResolver. query ( entityUri, new String [ ] { RawContacts. SOURCE_ID , Entity . DATA_ID , Entity . MIMETYPE , Entity . DATA1 } , null , null , null ) ;
  5.   try {
  6.   while ( c. moveToNext ( ) ) {
  7.     if ( ! c. isNull ( 1 ) ) {
  8.     String mimeType = c. getString ( 2 ) ;
  9.     String status = "" ;
  10.     if ( track. getNowPlaying ( ) ! = null && track. getNowPlaying ( ) . equals ( "true" ) )
  11.      status = "Listening to " + track. getName ( ) + " by " + track. getArtist ( ) ;
  12.     else
  13.      status = "Listened to " + track. getName ( ) + " by " + track. getArtist ( ) ;
  14.  
  15.     if ( mimeType. equals ( "vnd.android.cursor.item/vnd.fm.last.android.profile" ) ) {
  16.      ContentProviderOperation. Builder builder = ContentProviderOperation. newInsert ( ContactsContract. StatusUpdates . CONTENT_URI ) ;
  17.      builder. withValue ( ContactsContract. StatusUpdates . DATA_ID , c. getLong ( 1 ) ) ;
  18.      builder. withValue ( ContactsContract. StatusUpdates . STATUS , status ) ;
  19.      builder. withValue ( ContactsContract. StatusUpdates . STATUS_RES_PACKAGE , "fm.last.android" ) ;
  20.      builder. withValue ( ContactsContract. StatusUpdates . STATUS_LABEL , R. string . app_name ) ;
  21.      builder. withValue ( ContactsContract. StatusUpdates . STATUS_ICON , R. drawable . icon ) ;
  22.       if ( track. getDate ( ) ! = null ) {
  23.       long date = Long . parseLong ( track. getDate ( ) ) * 1000 ;
  24.       builder. withValue ( ContactsContract. StatusUpdates . STATUS_TIMESTAMP , date ) ;
  25.       }
  26.      operationList. add ( builder. build ( ) ) ;
  27.  
  28.      builder = ContentProviderOperation. newUpdate ( Co
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
目标检测(Object Detection)是计算机视觉领域的一个核心问题,其主要任务是找出图像中所有感兴趣的目标(物体),并确定它们的类别和位置。以下是对目标检测的详细阐述: 一、基本概念 目标检测的任务是解决“在哪里?是什么?”的问题,即定位出图像中目标的位置并识别出目标的类别。由于各类物体具有不同的外观、形状和姿态,加上成像时光照、遮挡等因素的干扰,目标检测一直是计算机视觉领域最具挑战性的任务之一。 二、核心问题 目标检测涉及以下几个核心问题: 分类问题:判断图像中的目标属于哪个类别。 定位问题:确定目标在图像中的具体位置。 大小问题:目标可能具有不同的大小。 形状问题:目标可能具有不同的形状。 三、算法分类 基于深度学习的目标检测算法主要分为两大类: Two-stage算法:先进行区域生成(Region Proposal),生成有可能包含待检物体的预选框(Region Proposal),再通过卷积神经网络进行样本分类。常见的Two-stage算法包括R-CNN、Fast R-CNN、Faster R-CNN等。 One-stage算法:不用生成区域提议,直接在网络中提取特征来预测物体分类和位置。常见的One-stage算法包括YOLO系列(YOLOv1、YOLOv2、YOLOv3、YOLOv4、YOLOv5等)、SSD和RetinaNet等。 四、算法原理 以YOLO系列为例,YOLO将目标检测视为回归问题,将输入图像一次性划分为多个区域,直接在输出层预测边界框和类别概率。YOLO采用卷积网络来提取特征,使用全连接层来得到预测值。其网络结构通常包含多个卷积层和全连接层,通过卷积层提取图像特征,通过全连接层输出预测结果。 五、应用领域 目标检测技术已经广泛应用于各个领域,为人们的生活带来了极大的便利。以下是一些主要的应用领域: 安全监控:在商场、银行
目标检测(Object Detection)是计算机视觉领域的一个核心问题,其主要任务是找出图像中所有感兴趣的目标(物体),并确定它们的类别和位置。以下是对目标检测的详细阐述: 一、基本概念 目标检测的任务是解决“在哪里?是什么?”的问题,即定位出图像中目标的位置并识别出目标的类别。由于各类物体具有不同的外观、形状和姿态,加上成像时光照、遮挡等因素的干扰,目标检测一直是计算机视觉领域最具挑战性的任务之一。 二、核心问题 目标检测涉及以下几个核心问题: 分类问题:判断图像中的目标属于哪个类别。 定位问题:确定目标在图像中的具体位置。 大小问题:目标可能具有不同的大小。 形状问题:目标可能具有不同的形状。 三、算法分类 基于深度学习的目标检测算法主要分为两大类: Two-stage算法:先进行区域生成(Region Proposal),生成有可能包含待检物体的预选框(Region Proposal),再通过卷积神经网络进行样本分类。常见的Two-stage算法包括R-CNN、Fast R-CNN、Faster R-CNN等。 One-stage算法:不用生成区域提议,直接在网络中提取特征来预测物体分类和位置。常见的One-stage算法包括YOLO系列(YOLOv1、YOLOv2、YOLOv3、YOLOv4、YOLOv5等)、SSD和RetinaNet等。 四、算法原理 以YOLO系列为例,YOLO将目标检测视为回归问题,将输入图像一次性划分为多个区域,直接在输出层预测边界框和类别概率。YOLO采用卷积网络来提取特征,使用全连接层来得到预测值。其网络结构通常包含多个卷积层和全连接层,通过卷积层提取图像特征,通过全连接层输出预测结果。 五、应用领域 目标检测技术已经广泛应用于各个领域,为人们的生活带来了极大的便利。以下是一些主要的应用领域: 安全监控:在商场、银行
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值