一、需求描述
需要識別圖片給圖片打上標簽,比如:圖片里面有楊冪,就是美女標簽
最開始准備用免費的騰訊優圖API,但是鼓搗了兩天怎么也搞不定,根據官方文檔來操作應該是不能用,放棄了,下面會詳細介紹坑點
后來試的百度AI開放平台的識別,發現頁面總是卡死,效果也不太准確
最后用的騰訊雲,發現是真他媽的香,滿足你的一切幻想
二、騰訊優圖踩坑過程
>>騰訊優圖<<圖片識別是免費的,一開始本打算用這個的,但是發現用不了,折騰了兩天,各種嘗試,以為自己代碼沒寫好,直到看到了他的SDK源碼,我放棄了
2.1 自己生成簽名
首先體驗界面就這樣顯示......
開發步驟:
>>簽名生成<<:
簽名的生成過程,只有下圖這么多,沒有詳細的描述,沒有可靠的的代碼demo
按照文檔,我自己生成了個簽名,並且去請求,返回403,禁止訪問,不清楚是簽名的問題還是后台維護的問題,感覺應該是后台的問題,代碼見下:
""" 需求:識別圖片內容為之打上標簽,圖片包含url形式的和image形式的 實現思路:python調用騰訊優圖api,參考騰訊官方文檔:https://open.youtu.qq.com/#/open/developer/join 1.按照新手指引-免費接入優圖AI開放平台 申請公有雲,獲取appid、SecretID、SecretKey 2.生成簽名:https://open.youtu.qq.com/#/develop/tool-authentication/auth 步驟:調用api需要配置header請求頭,請求頭需要鑒權簽名,鑒權簽名需要api密鑰。 鑒權簽名:https://cloud.tencent.com/document/product/866/17734 api密鑰的獲取:登陸騰訊雲https://console.cloud.tencent.com/cam/capi 代碼如下 """ import time import base64 import hmac import hashlib import binascii import hmac import requests import json import datetime import random from sys import getsizeof '''第一步:通過騰訊優圖申請公有雲獲取自己的api密鑰++++++++++++++++++++++++++++ ''' qq = '13++++QQ+++1' appid='1+++++4' SecretID='AKID++++++++++f39zY' SecretKey=' Zrt+++++++++++++++DK' '''第二步:生成簽名 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ''' # (1)拼接有效字符串 u = qq # 開發者創建應用時的QQ號 a = appid k = SecretID t = int(time.time()) #當前時間戳 e = t + 2592000 #簽名的有效期 此處定義為當前時間+30天 r = random.randint(0, 999999999) #隨機串,最長10位 f = '' original = f"{u}=10000&{a}=2011541224&{k}=AKID2ZkOXFyDRHZRlbPo93SMtzVY79kpAdGP&{e}=1432970065&{t}=1427786065&{r}=270494647&{f}=" # (2)生成簽名 def hash_hmac(secret_key,orignal): """生成簽名的函數 """ # 對orignal使用HMAC-SHA1算法進行簽名 SignTmp = hmac.new(bytes(secret_key,'utf-8'),bytes(orignal,'utf-8'), hashlib.sha1).digest() # 然后將orignal附加到簽名結果的末尾,再進行Base64編碼,得到最終的sign Sign = base64.b64encode(SignTmp+orignal.encode()) print(Sign) return Sign print(original) authorization=hash_hmac(SecretKey,original) """第三步:使用+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 參考:https://open.youtu.qq.com/#/open/developer/image-label """ url='https://api.youtu.qq.com/youtu/imageapi/imagetag' filepath = 'D:\\15859773d.png' payload = {'image':base64.b64encode(open(filepath, 'rb').read()).rstrip().decode('utf-8'), 'app_id':appid, 'seq':''} Length = str(getsizeof(payload)) headers={ 'Host':'api.youtu.qq.com', # 圖片雲服務器域名,固定為api.youtu.qq.com 'Content-Length':Length, # 整個請求包體內容的總長度,單位:字節(Byte) 'Content-Type':'text/json', #text/json表示json格式 'Authorization':authorization, # 多次有效簽名,用於鑒權,以Authorization為key } r = requests.post(url,data = json.dumps(payload) ,headers=headers) print(r) print(r.content)
2.2 調用SDK
既然自己生成簽名不行,那就調用>>現成的SDK<<吧,頁面就這,沒有寫支持的版本...
SDK的使用也是個謎:
一頓操作后我才發現,這個SDK還是個遠古SDK,只支持python 2.x,好吧,emmmm......
既然不支持python3,那我就去源碼里面把各種方法拿出來用,這些總該可以吧,然而,一頓操作后,我發現自己天真了:
-- 頭部信息對不上:
-- 基礎拼接字符串也對不上:
雖然各種對不上,但是手動生成的簽名請求返回403,死馬當活馬醫,試試SDK,將SDK中各個方法拿出來,用這里面的方法生成簽名去請求,返回401,也不行
總結:騰訊優圖實在有點坑,免費的果然。。。是免費的
代碼見下:
import time import base64 import hmac import hashlib import binascii import hmac import requests import json import datetime import random from sys import getsizeof def app_sign(appid,SecretID,SecretKey,puserid): now = int(time.time()) expired = 2592000 # 簽名的有效期 此處定義為當前時間+30天 rdm = random.randint(0, 999999999) #隨機串,最長10位 plain_text = 'a=' + appid + '&k=' + SecretID + '&e=' + str(expired) + '&t=' + str(now) + '&r=' + str( rdm) + '&u=' + puserid + '&f=' bin = hmac.new(SecretKey.encode(), plain_text.encode(), hashlib.sha1) s = bin.hexdigest() s = binascii.unhexlify(s) s = s + plain_text.encode('ascii') signature = base64.b64encode(s).rstrip() # 生成簽名 print(62,signature) return signature # 'EndITIThX1WqAkBfdPufvS9h7i9hPTEwMjcwMjk0Jms9QUtJRHVlN0tHdklPRW83OXZRZWJIaHFoSGFjTnI0MGYzOXpZJmU9MjU5MjAwMCZ0PTE2MjQ1MDQ0ODcmcj0yMTU2MjQ3ODkmdT0xMzE1NDU4NTcxJmY9' '''第一步:通過騰訊優圖申請公有雲獲取自己的api密鑰++++++++++++++++++++++++++++ ''' qq = '1===============71' appid='19899999999999999444' SecretID='AK0000000000000000039zY' SecretKey=' Z666666666666666666666DK' '''第二步:生成簽名 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ''' authorization = app_sign(appid=appid, SecretID=SecretID,SecretKey=SecretKey,puserid=qq) """第三步:使用+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 參考:https://open.youtu.qq.com/#/open/developer/image-label """ headers={ 'Content-Type':'text/json', #text/json表示json格式 'Authorization':authorization, # 多次有效簽名,用於鑒權,以Authorization為key } url='https://api.youtu.qq.com/youtu/imageapi/imagetag' filepath = 'D:\\25a82978e15859773d.png' payload = {'image':base64.b64encode(open(filepath, 'rb').read()).rstrip().decode('utf-8'), 'app_id':appid, 'seq':''} r = requests.post(url,data = json.dumps(payload) ,headers=headers) print(999,r) print(999,r.content)
三、百度AI開放平台和騰訊雲對比
首先這兩個平台都是要收費的,價格不一,騰訊雲有10000張免費額度
對比了一些圖片,發現騰訊的更好用一些,更准確,並且簽名什么的繁瑣步驟直接給封裝好的SDK支持大多數python版本,並且可以動態生成代碼,詳見下一節,下面展示結果:
百度識圖: https://ai.baidu.com/tech/imagerecognition/object_detect
騰訊雲識別:
入口:騰訊雲主頁- 產品 - 人工智能 - 圖像識別 - DEMO體驗
四、騰訊雲 圖片識別
騰訊雲:https://cloud.tencent.com/
圖片識別操作指引: https://cloud.tencent.com/document/product/865/17630
騰訊雲沒人有10000張圖片的免費額度,各個模塊都有,但是應該是有有效期一個月的
騰訊雲的用戶體驗不要太好了,你想要的他都有,除了收費,還是rmb玩家體驗好,騰訊優圖雖然免費,但是簡直 emmm...
4.1 准備階段和圖片識別流程概述
- 登錄賬號
注冊並通過實名認證后,您。如果沒有賬號,請參考 注冊騰訊雲教程 。
- 創建密鑰
完成注冊后,您需要在 訪問管理控制台 創建密鑰。AppID、SecretID 和 SecretKey 是您進行應用開發的唯一憑證,請務必妥善保管。
- 生成簽名
通過簽名來驗證請求的合法性,您可以使用主賬號的 AppID、SecretID 和 SecretKey 生成簽名,具體簽名生成方法請參閱 接口鑒權 。
這個簽名算法可以自己實現,但是騰訊雲已經提供了SDK,里面封裝的有,簽名這個步驟基本不需要考慮,參考下面 4.2 安裝SDK調用就好了
4.2 了解API 和 SDK
我們為您提供了簡單易用的 API 接口,您可以查看並調用 圖像分析 。
可以直接進入 >> 圖片標簽<< 查看這個API的功能,了解輸入參數、輸出參數,然后直接找到下方的SDK:
雲 API 3.0 提供了配套的開發工具集(SDK),支持多種編程語言,能更方便的調用 API,支持Python 2.7, 3.6-3.9 版本,見下:
SDK里面有詳細的描述,支持pip安裝,也支持下載安裝,並且有非常清楚的注釋版本的代碼demo可供參考,該demo不是圖像識別的的,整體代碼框架一樣,具體方法參數需要自己修改
4.3 圖片識別開發代碼
SDK里面給出的不是圖像識別的代碼,那么具體代碼怎么調用書寫呢?這時候就要用騰訊雲的另一個超好用的功能:API Explorer
這個界面直接可以在線調用,逐步演示簽名生成過程,還有參數詳細說明,最主要的是可以實時生成代碼太香了
這個代碼只需要自己復制走,稍微更改一下參數就好了,當然還有很多參數可以自定義,詳細的參考4.2中SDK界面demo:
我根據SDK中詳細代碼, 對在線生成的代碼簡單增加了一些注釋和參數,
以及對返回的數據進行了解析轉化,可以參考:
# -*- coding: utf-8 -*- import json import base64 import logging from tencentcloud.common import credential # 導入可選配置類 from tencentcloud.common.profile.client_profile import ClientProfile from tencentcloud.common.profile.http_profile import HttpProfile from tencentcloud.common.exception.tencent_cloud_sdk_exception import TencentCloudSDKException # 根據自己使用的模塊,導入對應產品模塊的client models ++++++++++++++++++++++++++ from tencentcloud.tiia.v20190529 import tiia_client, models def get_imgtag(img_path): try: # 實例化一個認證對象,騰訊雲賬戶secretId,secretKey,需注意密鑰對的保密+++++++++++++++++++++++++ cred = credential.Credential(SecretID, SecretKey) # 實例化一個http選項,可選的,沒有特殊需求可以跳過。 httpProfile = HttpProfile() # 如果需要指定proxy訪問接口,可以按照如下方式初始化hp # httpProfile = HttpProfile(proxy="http://用戶名:密碼@代理IP:代理端口") # httpProfile.protocol = "https" # 在外網互通的網絡環境下支持http協議(默認是https協議),建議使用https協議 # httpProfile.keepAlive = True # 狀態保持,默認是False # httpProfile.reqMethod = "POST" # get請求(默認為post請求) httpProfile.reqTimeout = 30 # 請求超時時間,單位為秒(默認60秒)+++++++++++++++++++++++++++ httpProfile.endpoint = "tiia.tencentcloudapi.com" # 指定接入地域域名(默認就近接入) # 實例化一個client選項,可選的,沒有特殊需求可以跳過。 clientProfile = ClientProfile() # clientProfile.signMethod = "TC3-HMAC-SHA256" # 指定簽名算法 # clientProfile.language = "en-US" # 指定展示英文(默認為中文) clientProfile.httpProfile = httpProfile # 根據自己需求,實例化要請求產品client對象 client = tiia_client.TiiaClient(cred, "ap-shanghai", clientProfile) # 實例化一個實例信息查詢requests請求對象,每個接口都會對應一個request對象。 req = models.DetectLabelRequest() params = { "ImageBase64": base64.b64encode(open(img_path, 'rb').read()).rstrip().decode('utf-8'), # 需要這樣轉碼計算++++++++++++++++++ "Scenes": ["CAMERA"] # 常用:WEB,針對網絡圖片優化; CAMERA,針對手機攝像頭拍攝圖片優化,默認WEB,不同模式結果不同,自行選擇 } req.from_json_string(json.dumps(params)) resp = client.DetectLabel(req) # 輸出json格式的字符串回包:Labels、CameraLabels、AlbumLabels、NewsLabels、RequestId # print(resp.to_json_string(indent=2)) # 也可以取出單個值,如只看Labels # print(resp.Labels) # return resp.Labels # "Scenes"為默認的WEB時 ret_list = [] # 返回列表項看似是字典,其實是DetectLabelItem類對象,不能序列化,不能用get,反序列化也沒用,只能用點語法取值,轉化為字典 for DetectLabelItem in resp.CameraLabels: # "Scenes"為CAMERA時 DetectLabelItem_to_dict = {} # 可信度 1-100 DetectLabelItem_to_dict['Confidence'] = int(DetectLabelItem.Confidence) # Confidence = int(lable.get('Confidence')) # 描述 DetectLabelItem_to_dict['Name'] = DetectLabelItem.Name # 一級標簽 DetectLabelItem_to_dict['FirstCategory'] = DetectLabelItem.FirstCategory # FirstCategory = lable.get('FirstCategory') # 二級標簽 DetectLabelItem_to_dict['SecondCategory'] = DetectLabelItem.SecondCategory ret_list.append(DetectLabelItem_to_dict) return ret_list except TencentCloudSDKException as err: print(err) if __name__ == '__main__': SecretID = 'AKxxxoooxxxooo8g17w' SecretKey = 'bvxxxoooxxxoooxoxoIM' img_path = 'D:\\代碼\\xxoo\\wechat_files\\微信圖片_20210625142623.jpg' get_imgtag(SecretID, SecretKey, img_path)
4.4 查看調用
可以登錄 騰訊雲控制台 ,該平台可以看到每一次調用的情況,查看 圖像分析 服務的調用情況。