摘要:語(yǔ)音識(shí)別,語(yǔ)義理解一站式解決之智能照相機(jī)人臉識(shí)別如果有代碼排版和圖片顯示問(wèn)題,請(qǐng)?jiān)L問(wèn)博客。前面寫(xiě)了兩篇語(yǔ)音識(shí)別,語(yǔ)義理解的博文,分別是語(yǔ)音在線聽(tīng)書(shū)和語(yǔ)音記帳軟件,本篇是語(yǔ)音智能照相機(jī)。
語(yǔ)音識(shí)別,語(yǔ)義理解一站式解決之智能照相機(jī)(人臉識(shí)別,olami)
如果有代碼排版和圖片顯示問(wèn)題,請(qǐng)?jiān)L問(wèn)CSDN博客。
轉(zhuǎn)載請(qǐng)注明CSDN博文地址:http://blog.csdn.net/ls0609/a...
olami sdk實(shí)現(xiàn)了把錄音或者文字轉(zhuǎn)化為用戶可以理解的json字符串從而實(shí)現(xiàn)語(yǔ)義理解,用戶可以定義自己的
語(yǔ)義,通過(guò)這種方式可以實(shí)現(xiàn)用戶需要的語(yǔ)義理解。前面寫(xiě)了兩篇語(yǔ)音識(shí)別,語(yǔ)義理解的博文,分別是語(yǔ)音
在線聽(tīng)書(shū)和語(yǔ)音記帳軟件,本篇是語(yǔ)音智能照相機(jī)。
1.智能照相機(jī)的功能
手機(jī)后攝像頭像素比較高,如果用后設(shè)想頭對(duì)準(zhǔn)自己自拍,那么看不到屏幕的情況下怎么知道
自己在不在鏡頭中呢?而本篇做的智能照相機(jī)就可以為您解決這個(gè)問(wèn)題。
想要做的是這樣一個(gè)照相機(jī)app,可以語(yǔ)音切換攝像頭,人臉識(shí)別并語(yǔ)音播報(bào)識(shí)別的人臉是否在屏幕中央,
是偏向哪里,當(dāng)人臉居中的時(shí)候,提示用戶可以拍照了,用戶說(shuō)“拍照”,“茄子”就會(huì)自動(dòng)抓拍并保存圖
片在手機(jī)中。
抓了兩張應(yīng)用運(yùn)行時(shí)的圖片:
2.eclipse中的lib目錄結(jié)構(gòu)如下
assets下面的事tts播報(bào)的資源文件
libs目錄下,
libtts.so tts播報(bào)所需的庫(kù)文件
libspeex.so 語(yǔ)音識(shí)別所需的庫(kù)文件
libolamsc.so 語(yǔ)音識(shí)別所需的庫(kù)文件
tts.jar tts播報(bào)所需的庫(kù)文件
voicesdk_android.jar 語(yǔ)音識(shí)別所需的庫(kù)文件
3.AndroidManifest.xml
package="com.olami"
android:versionCode="1"
android:versionName="1.0" >
需要錄音,網(wǎng)絡(luò),讀寫(xiě)sd卡,拍照等權(quán)限。
4.layout布局xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
在surfaceview中自定義了一個(gè)FaceView,faceview用來(lái)顯示抓拍的人臉。
屏幕最下方有個(gè)button,因?yàn)檫@個(gè)版本暫時(shí)不支持語(yǔ)音喚醒功能(后續(xù)添加后再更新),添加一個(gè)button用于用戶想隨時(shí)說(shuō)拍照的時(shí)候點(diǎn)擊觸發(fā)用。
5.MainActivity.java 和FaceView.java
1.MainActivity.Java
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); setContentView(R.layout.layout_camera); initHandler();//用于處理錄音狀態(tài)回調(diào)的消息 initView(); //初始化界面 initViaVoiceRecognizerListener(); //初始化olami語(yǔ)音回調(diào)監(jiān)聽(tīng) init(); //初始化olami語(yǔ)音識(shí)別sdk initTts(); //初始化tts語(yǔ)音播報(bào) DisplayMetrics dm = new DisplayMetrics();//定義DisplayMetrics對(duì)象 getWindowManager().getDefaultDisplay().getMetrics(dm);//取得窗口屬性 mScreenCenterx = dm.widthPixels/2;//窗口的寬度 mScreenCentery = dm.heightPixels/2; //窗口的高度
}
以下是olamisdk的初始化
public void init()
{
mOlamiVoiceRecognizer = new OlamiVoiceRecognizer(MainActivity.this); TelephonyManager telephonyManager= (TelephonyManager) this.getSystemService( this.getBaseContext().TELEPHONY_SERVICE); String imei=telephonyManager.getDeviceId(); mOlamiVoiceRecognizer.init(imei);//設(shè)置身份標(biāo)識(shí),可以填null //設(shè)置識(shí)別結(jié)果回調(diào)listener mOlamiVoiceRecognizer.setListener(mOlamiVoiceRecognizerListener); //設(shè)置支持的語(yǔ)音類型,優(yōu)先選擇中文簡(jiǎn)體 mOlamiVoiceRecognizer.setLocalization( OlamiVoiceRecognizer.LANGUAGE_SIMPLIFIED_CHINESE); mOlamiVoiceRecognizer.setAuthorization( "51a4bb56ba954655a4fc834bfdc46af1", "asr", "68bff251789b426896e70e888f919a6d", "nli"); //注冊(cè)Appkey,在olami官網(wǎng)注冊(cè)應(yīng)用后生成的appkey //注冊(cè)api,請(qǐng)直接填寫(xiě)“asr”,標(biāo)識(shí)語(yǔ)音識(shí)別類型 //注冊(cè)secret,在olami官網(wǎng)注冊(cè)應(yīng)用后生成的secret //注冊(cè)seq ,請(qǐng)?zhí)顚?xiě)“nli” //錄音時(shí)尾音結(jié)束時(shí)間,建議填//2000ms mOlamiVoiceRecognizer.setVADTailTimeout(2000); //設(shè)置經(jīng)緯度信息,不愿上傳位置信息,可以填0 mOlamiVoiceRecognizer.setLatitudeAndLongitude( 31.155364678184498,121.34882432933009);
}
定義OlamiVoiceRecognizerListener,此處代碼就不貼了。
onError(int errCode)//出錯(cuò)回調(diào),可以對(duì)比官方文檔錯(cuò)誤碼看是什么錯(cuò)誤
onEndOfSpeech()//錄音結(jié)束
onBeginningOfSpeech()//錄音開(kāi)始
onResult(String result, int type)//result是識(shí)別結(jié)果JSON字符串
onCancel()//取消識(shí)別,不會(huì)再返回識(shí)別結(jié)果
onUpdateVolume(int volume)//錄音時(shí)的音量,1-12個(gè)級(jí)別大小音量
以下是handler消息處理,包含語(yǔ)義解析
private void initHandler()
{ mHandler = new Handler(){ @Override public void handleMessage(Message msg) { switch (msg.what){ case MessageConst.CLIENT_ACTION_START_RECORED: mBtnStart.setText("錄音中"); break; case MessageConst.CLIENT_ACTION_STOP_RECORED: mBtnStart.setText("識(shí)別中"); break; case MessageConst.CLIENT_ACTION_CANCEL_RECORED: mBtnStart.setText("開(kāi)始"); break; case MessageConst.CLIENT_ACTION_ON_ERROR: mBtnStart.setText("開(kāi)始"); break; case MessageConst.CLIENT_ACTION_UPDATA_VOLUME: //mTextViewVolume.setText("音量: "+msg.arg1); break; case MessageConst.SERVER_ACTION_RETURN_RESULT: mBtnStart.setText("開(kāi)始"); try{ String message = (String) msg.obj; String input = null; JSONObject jsonObject = new JSONObject(message); JSONArray jArrayNli = jsonObject.optJSONObject("data").optJSONArray("nli"); JSONObject jObj = jArrayNli.optJSONObject(0); JSONArray jArraySemantic = null; if(message.contains("semantic")) { jArraySemantic = jObj.getJSONArray("semantic"); String modifier = jArraySemantic.optJSONObject(0).optJSONArray( "modifier").optString(0); if("take_photo".equals(modifier)) capture(); else if("switch_camera".equals(modifier)) switchCamera(); } else{ Log.i("ppp","result error"); } } catch(Exception e) { e.printStackTrace(); } break; case MessageConst.CLIENT_ACTION_UPDATA_FACEDECTION_DATA: if(mIsRecording) break; RectF rect = (RectF) msg.obj; mLeft = rect.left; mRight = rect.right; mTop = rect.top; mBottom = rect.bottom; float centerx = mLeft +(mRight - mLeft)/2; float centery = mTop + (mBottom-mTop)/2; String promptString = ""; if(centerx100) promptString = "位置偏左,"; else if((centerx > mScreenCenterx)&& (Math.abs(centerx -mScreenCenterx)>100)) promptString = "位置偏右,"; if((centery < mScreenCentery)&&( Math.abs(mScreenCentery-centery) >200)) { if("".equals(promptString)) promptString = "位置偏上"; else promptString += "并且偏上"; } else if((centery > mScreenCentery)&& (Math.abs(centery -mScreenCenterx)>200)) { if("".equals(promptString)) promptString = "位置偏下"; else promptString += "并且偏下"; } if("".equals(promptString)) { promptString = "位置已經(jīng)居中,可以拍照了"; mIsCenter = true; } else { mIsCenter = false; } ITtsListener ttsListener = new ITtsListener() { @Override public void onPlayEnd() { if(mIsCenter) { if(mOlamiVoiceRecognizer != null) mOlamiVoiceRecognizer.start(); } } @Override public void onPlayFlagEnd(String arg0) { } @Override public void onTTSPower(long arg0) { } }; TtsPlayer.playText(MainActivity.this, promptString, ttsListener,Tts.TTS_SYSTEM_PRIORITY); break; } } }; }
在MessageConst.SERVER_ACTION_RETURN_RESULT消息中,通過(guò)解析服務(wù)器返回的json字符串,可以找到modifier這個(gè)字段的值,如果是take_photo表示拍照,如果是switch_camera表示切換攝像頭。
當(dāng)用戶說(shuō)拍照或者茄子的時(shí)候,服務(wù)器返回如下json字符串:
[
{
"desc_obj": { "status": 0 }, "semantic": [ { "app": "camera", "input": "拍照", "slots": [ ], "modifier": [ "take_photo" ], "customer": "58df512384ae11f0bb7b487e" } ], "type": "camera"
}
]
這個(gè)拍照,茄子等語(yǔ)法都是自己定義的,詳細(xì)請(qǐng)看:
olami開(kāi)放平臺(tái)語(yǔ)法編寫(xiě)簡(jiǎn)介:http://blog.csdn.net/ls0609/a...
olami開(kāi)放平臺(tái)語(yǔ)法官方介紹:https://cn.olami.ai/wiki/?mp=...
? 2.人臉識(shí)別FaceView.java
public class FaceView extends View {
private Camera.Face[] mFaces; private Paint mPaint; private Matrix matrix = new Matrix(); private RectF mRectF = new RectF(); private Handler mHandler; private long mCurrentTime; public void setFaces(Camera.Face[] faces) { mFaces = faces; invalidate(); } public FaceView(Context context) { super(context); init(context); } public FaceView(Context context, AttributeSet attrs) { super(context, attrs); init(context); } public FaceView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(context); } public void init(Context context) { mPaint = new Paint(); mPaint.setColor(Color.RED); mPaint.setStrokeWidth(5f); mPaint.setStyle(Paint.Style.STROKE); } public void setHandler(Handler handler) { mHandler = handler; } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); if (mFaces == null || mFaces.length < 0) { return; } //準(zhǔn)備矩形框 MainActivity.prepareMatrix(matrix, false, 270, getWidth(), getHeight()); canvas.save(); matrix.postRotate(0); canvas.rotate(-0); RectF tempRectF = new RectF(); long tempTime = System.currentTimeMillis(); for (int i = 0; i < mFaces.length; i++) { mRectF.set(mFaces[i].rect);//獲取face矩形框值 float temp = mRectF.top; mRectF.top = -mRectF.bottom; mRectF.bottom = - temp; //上下交換 matrix.mapRect(mRectF); canvas.drawRect(mRectF, mPaint);//繪制矩形框 tempRectF.set(mRectF); if((mCurrentTime == 0) ||((tempTime-mCurrentTime)/1000) >= 4) {//超過(guò)4秒,發(fā)送一次識(shí)別face矩形框值 mHandler.sendMessage(mHandler.obtainMessage( MessageConst.CLIENT_ACTION_UPDATA_FACEDECTION_DATA, tempRectF)); mCurrentTime = tempTime; } Log.i("ppp","mRectF.left = "+mRectF.left+" mRectF.right = "+mRectF.right); } canvas.restore(); }
}
自定義FaceView中,由于旋轉(zhuǎn)了270度,所以需要face矩形框上下值進(jìn)行交換,不然人臉識(shí)別總是左右或者上下不能追蹤。每隔4秒發(fā)送一次矩形框的值,在MainActivity.java的handler中收到這個(gè)消息并進(jìn)行是否居中的判斷。
case MessageConst.CLIENT_ACTION_UPDATA_FACEDECTION_DATA:
if(mIsRecording) break; RectF rect = (RectF) msg.obj; mLeft = rect.left; mRight = rect.right; mTop = rect.top; mBottom = rect.bottom;//保存上下左右的矩形框值 float centerx = mLeft +(mRight - mLeft)/2;//獲取矩形框橫向中心點(diǎn)位置 float centery = mTop + (mBottom-mTop)/2;//獲取矩形框縱向中心點(diǎn)位置 String promptString = ""; if(centerx100) promptString = "位置偏左,"; else if((centerx > mScreenCenterx)&& (Math.abs(centerx -mScreenCenterx)>100)) promptString = "位置偏右,"; if((centery < mScreenCentery)&&( Math.abs(mScreenCentery-centery) >200)) { if("".equals(promptString)) promptString = "位置偏上"; else promptString += "并且偏上"; } else if((centery > mScreenCentery)&& (Math.abs(centery -mScreenCenterx)>200)) { if("".equals(promptString)) promptString = "位置偏下"; else promptString += "并且偏下"; } if("".equals(promptString)) { promptString = "位置已經(jīng)居中,可以拍照了"; mIsCenter = true; } else { mIsCenter = false; } ITtsListener ttsListener = new ITtsListener() { @Override public void onPlayEnd() { if(mIsCenter) { if(mOlamiVoiceRecognizer != null) mOlamiVoiceRecognizer.start(); } } @Override public void onPlayFlagEnd(String arg0) { } @Override public void onTTSPower(long arg0) { } }; TtsPlayer.playText(MainActivity.this, promptString, ttsListener,Tts.TTS_SYSTEM_PRIORITY);
break;
可以獲得屏幕的中心點(diǎn)和人臉識(shí)別的矩形框的中心點(diǎn),對(duì)比橫向和縱向的中心點(diǎn)大小和絕對(duì)值差,當(dāng)橫向的值差100像素以上就認(rèn)為橫向不居中,并且根據(jù)大小分居左和居右,縱向大小差值在200像素以上認(rèn)為縱向不居中,并且根據(jù)大小分偏上和偏下,這個(gè)100,200像素值用戶可以自己調(diào)節(jié)到合適的值。
調(diào)用TtsPlayer.playText提示,當(dāng)播報(bào)結(jié)束后回調(diào)到onPlayEnd() ,如果居中那么已經(jīng)提示用戶可以拍照了,此時(shí)啟動(dòng)錄音程序,用戶不用點(diǎn)擊button也不用喚醒,只許說(shuō)拍照或者茄子就可以拍照了。
6.源碼下載鏈接
https://pan.baidu.com/s/1qXITWs8
7.相關(guān)鏈接
語(yǔ)音在線聽(tīng)書(shū):http://blog.csdn.net/ls0609/a...
語(yǔ)音記賬demo:http://blog.csdn.net/ls0609/a...
olami開(kāi)放平臺(tái)語(yǔ)法編寫(xiě)簡(jiǎn)介:http://blog.csdn.net/ls0609/a...
olami開(kāi)放平臺(tái)語(yǔ)法官方介紹:https://cn.olami.ai/wiki/?mp=...
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/67610.html
摘要:前言阿里巴巴機(jī)器智能實(shí)驗(yàn)室線下智能團(tuán)隊(duì)從年底開(kāi)始涉及線下智能領(lǐng)域,從算法工程產(chǎn)品化業(yè)務(wù)落地多個(gè)方面入手,與合作伙伴們一起取得了一些小小的成績(jī)。目前,該套工具作為推薦的量化工具廣泛應(yīng)用在阿里集團(tuán)內(nèi)多個(gè)線下業(yè)務(wù)場(chǎng)景中。 showImg(https://segmentfault.com/img/remote/1460000019246850); 阿里妹導(dǎo)讀:AI 技術(shù)已經(jīng)從互聯(lián)網(wǎng)走向零售、...
摘要:這群小伙伴們堅(jiān)信的強(qiáng)大能力,堅(jiān)信可以模擬人類很多的感官功能,包括視覺(jué)聽(tīng)覺(jué),甚至包括思考能力給安裝上一個(gè)機(jī)械手臂,甚至可以模擬人類的肢體功能,這就是阿里云人工智能的能力。 阿里云人工智能 ET, 代表的是阿里云語(yǔ)音識(shí)別、語(yǔ)音合成、自然語(yǔ)言理解、實(shí)時(shí)圖像識(shí)別、機(jī)器學(xué)習(xí)的綜合技術(shù),背后是阿里云飛天系統(tǒng)強(qiáng)大的計(jì)算能力。 可是這么高大上的 ET,最近居然開(kāi)始不務(wù)正業(yè)了,來(lái)看看它都干了啥?。?! 視...
摘要:的人工智能版圖人工智能版圖由應(yīng)用平臺(tái)框架三大部分組成應(yīng)用層是提供各種應(yīng)用服務(wù),比如平臺(tái)層是平臺(tái)。應(yīng)用層主推三大成熟應(yīng)用基于深度學(xué)習(xí)的圖像和視頻分析它能實(shí)現(xiàn)對(duì)象與場(chǎng)景檢測(cè)人臉?lè)治雒娌勘容^人臉識(shí)別名人識(shí)別圖片調(diào)節(jié)等功能。AWS的人工智能版圖 AWS人工智能版圖由:應(yīng)用、平臺(tái)、框架三大部分組成 AI應(yīng)用層:是提供各種應(yīng)用服務(wù),比如Amazon Rekognition、Polly...
摘要:的人工智能版圖人工智能版圖由應(yīng)用平臺(tái)框架三大部分組成應(yīng)用層是提供各種應(yīng)用服務(wù),比如平臺(tái)層是平臺(tái)。應(yīng)用層主推三大成熟應(yīng)用基于深度學(xué)習(xí)的圖像和視頻分析它能實(shí)現(xiàn)對(duì)象與場(chǎng)景檢測(cè)人臉?lè)治雒娌勘容^人臉識(shí)別名人識(shí)別圖片調(diào)節(jié)等功能。 AWS的人工智能版圖AWS人工智能版圖由:應(yīng)用、平臺(tái)、框架三大部分組成AI應(yīng)用層:是提供各種...
閱讀 1708·2023-04-25 18:27
閱讀 1472·2021-10-19 11:44
閱讀 641·2021-10-14 09:42
閱讀 2208·2021-10-11 10:59
閱讀 2842·2021-09-24 09:47
閱讀 1795·2019-08-30 14:20
閱讀 1221·2019-08-30 14:08
閱讀 793·2019-08-29 15:15