一、翔云 人工智能開放平臺
- API文檔
- 開發示例下載
二、編譯openSSL支持libcurl的https訪問
- 安裝SSL依賴庫openSSL(使用工具wget)
- libcurl庫重新配置,編譯,安裝
- 運行(運行需添加動態庫為環境變量)
三、編程實現人臉識別
四、Base64編碼
五、RGB顏色模型(用于表示圖像中的顏色信息)
六、BMP 圖像以像素矩陣的形式存儲
七、Base64數據格式轉換
八、加入圖片base64編碼
九、人臉識別完整代碼及功能點實現現象
一、翔云 人工智能開放平臺
翔云 人工智能開放平臺
下面通過人工智能OCR識別平臺翔云的使用,掌握調庫調API開發的一般步驟,其他的平臺也基本類似。
API文檔
開發示例下載
C++示例代碼
strPostData.Format(_T("img=%s&key=%s&secret=%s&typeId=%d&format=xml"),strImageBase64,strKey,strSecret,nTypeID);
Java示例代碼
java大多直接調庫,非常簡潔,這也是它開發效率高的原因之一。
二、編譯openSSL支持libcurl的https訪問
?那是因為在編譯libcurl庫的時候,由于翔云接口是https:開頭的,需要選擇支持SSL。
./configure --with -ssl
?我們訪問的接口是https開頭的,要進行身份驗證和數據加密的,體現在我們的key和secret。
?那我們就要回到/curl-7.71.1
路徑下,刪除rm _install -rf
上次編譯出來的文件夾,重新編譯支持SSL的庫。由/docs/INSTALL.md
我們可以得知要想支持SSL,就得./configure --with-ssl
chmod +x configure
sudo ./configure --prefix=$PWD/_install --with-ssl
編譯錯誤
cheking for SSL_connect in -lssl... (cached)no no
configure:error:openSSL libs and/or directories were not found where specified!
安裝SSL依賴庫openSSL(使用工具wget)
?想要支持SSL必須要有依賴庫,需要系統中已經安裝好了SSL。
?我們需要安裝openSSL.tar
利用linux的開源工具下載:wget是Linux中的一個下載文件的工具,wget是在Linux下開發的開放源代碼的軟件。
百度搜索技巧:wget openSSL.tar
wget https://www.openssl.org/source/openssl-1.1.1a.tar.gz
tar xvf openssl-1.1.1a.tar.gz
進入文件夾,直接去看他的INSTALL。
?為了避免到時候編譯這個curl又要去配置SSL這個庫,我們直接把SSL安裝到默認的系統位置去(一般默認是在/usr/local
底下),所以不指定安裝路徑了,直接在/openssl-1.1.1a
路徑下,配置
./config
make
sudo make install
安裝配置openssl庫時間比較長建議網絡穩定ssh建議用MobaXterm,vscodessh安裝可能會掉
加 sudo就肯定安裝在了usr/local
中,非工作目錄無權限
libcurl庫重新配置,編譯,安裝
回到/curl-7.71.1/目錄下重新進行配置:
chmod +x configure
sudo ./configure --prefix=$PWD/_install --with-ssl
sudo make
make install
運行(運行需添加動態庫為環境變量)
生成了可執行文件./a.out直接運行可能會報錯(我沒有報錯,可能是我用的Ubuntu22.04)。
原因是運行時要鏈接動態庫,沒有添加環境變量
cd /home/orangepi/curl-7.71.1/_install/lib
export LD_LIBRARY_PATH=/home/orangepi/curl-7.71.1/_install/lib
永久有效,配置環境變量,要改配置文件
在Linux系統上,如果你希望將libcurl庫的路徑添加到永久環境變量中,你可以編輯shell配置文件,例如bash的.bashrc
文件。以下是在bash shell中將libcurl庫路徑添加到LD_LIBRARY_PATH
環境變量的步驟:
-
打開
.bashrc
文件,可以使用文本編輯器如nano
、vim
、gedit
等。nano ~/.bashrc
-
在文件的末尾添加以下行,其中
/path/to/libcurl
是libcurl庫的實際路徑。export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/path/to/libcurl
替換
/path/to/libcurl
為libcurl庫的實際路徑。 -
保存并關閉文件。
-
使更改生效。可以通過運行以下命令重新加載
.bashrc
文件:source ~/.bashrc
或者,你可以注銷并重新登錄。
現在,libcurl庫的路徑將在每次啟動新shell時自動添加到LD_LIBRARY_PATH
中。這確保了libcurl庫在系統范圍內可用。請注意,這只對當前用戶生效。如果你希望所有用戶都能訪問libcurl庫,你可能需要將環境變量設置添加到/etc/environment
文件中,這需要超級用戶權限。
echo $PATH // 獲得當前環境變量的值
pwd // 獲得當前路徑
修改工作目錄下的 .bashrc
隱藏文件,配置命令終端的
vi /home/orangepi/.bashrc
在文件最后一行加入:
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/orangepi/curl-7.71.1/_install/lib
source /home/orangepi/.bashrc 加載配置文件,馬上生效配置。
三、編程實現人臉識別
翔云人臉識別API文檔
ocr.c
#include <stdio.h>
#include <curl/curl.h>
#include <string.h>
#include <stdlib.h>// 定義bool類型和常量
typedef unsigned int bool; // 數據類型別名用typedef
#define true 1
#define false 0// 回調函數,讀取從OCR后臺返回的數據 前面打開百度的例子是將內容讀取到本地文件fd里面
size_t readData(void *ptr, size_t size, size_t nmemb, void *stream)
{// 在這里處理返回的數據,例如保存到文件或進行其他處理char buf[1024] = {'\0'};strncpy(buf, ptr, 1024);printf("============================= get data ===========================\n");printf("%s\n", buf);return size * nmemb;
}// 根據文檔,接口調用方法為post請求
bool postUrl()
{CURL *curl;CURLcode res;char *postString = NULL; // 空指針,要開辟空間// 根據翔云平臺的接口要求 分開定義,然后字符串拼接char *img1 = NULL; // 圖片base64流char *img2 = NULL;char *key = "JFD5c1iBh9LVqPkkZMxxxx";char *secret = "76f444813fc945bd9543e4d7e086xxxx";int typeId = 21;char *format = "xml";// 字符串拼接postString = (char *)malloc(strlen(key) + strlen(secret) + 2048);sprintf(postString, "img1=%s&img2=%s&key=%s&secret=%s&typeId=%d&format=%s", "", "", key, secret, typeId, format);curl = curl_easy_init();if (curl){// 指定cookie緩存文件if (curl_easy_setopt(curl, CURLOPT_COOKIEFILE, "/tmp/cookie.txt") != CURLE_OK){fprintf(stderr, "Failed to set cookie file\n");// 處理錯誤return false; // 在設置失敗時,直接返回}// 指定post傳輸內容,get請求將URL和postString一次性發送curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postString);// 指定urlcurl_easy_setopt(curl, CURLOPT_URL, "https://netocr.com/api/faceliu.do");// 回調函數讀取返回值curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, readData);// 執行請求res = curl_easy_perform(curl);if (res != CURLE_OK){fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));// 處理錯誤return false;}// 清理資源curl_easy_cleanup(curl);}// 釋放動態分配的內存free(postString);return true;
}int main(void)
{postUrl();return 0;
}
編譯
gcc ocr.c -I /home/orangepi/curl-7.71.1/_install/include/ -L /home/orangepi/curl-7.71.1/_install/lib/ -lcurl
運行
成功運行后,已經可以看到已經收到了翔云后臺的反饋:
四、Base64編碼
Base64 是一種二進制到文本編碼方式,通過將二進制數據編碼為 ASCII 字符集中的字符,使得數據能夠以文本形式傳輸,而不會被改變。Base64 編碼通常用于在文本協議中傳輸二進制數據,例如電子郵件的附件、圖片的網址傳輸等。
Base64 編碼的基本原理是將每三個字節的數據(24 位)轉換為四個 Base64 字符。這樣,原始數據的大小會增加約 1/3。
Base64 字符集通常包含 64 個字符,包括:
- 26 個大寫字母: A-Z
- 26 個小寫字母: a-z
- 10 個數字: 0-9
- 兩個額外字符: + 和 /
Base64 不使用常見的字符,因此它是一種安全的編碼方式,適用于在文本協議中傳輸二進制數據。
編碼過程如下:
- 將數據按每三個字節(24 位)進行分組。
- 將每組數據劃分為四個 6 位的片段。
- 將這些 6 位的片段轉換為 Base64 字符。
Base64 解碼則是編碼的逆過程,將 Base64 字符轉換回原始的二進制數據。在編碼和解碼過程中,Base64 字符集提供了一種標準的、文本友好的表示形式,使得數據在各種環境中都能夠被正確處理。
示例:
原始數據: Hello, World!
Base64 編碼:SGVsbG8sIFdvcmxkIQ==
在編程中,大多數編程語言都提供了 Base64 編碼和解碼的庫或函數,方便開發者在應用中使用。
五、RGB顏色模型(用于表示圖像中的顏色信息)
RGB(Red, Green, Blue)是一種顏色模型,用于表示圖像中的顏色信息。在 RGB 模型中,每個像素的顏色由紅色(R)、綠色(G)、藍色(B)三個分量的亮度組合而成。每個分量的取值通常在 0 到 255 之間,其中 0 表示最小亮度,255 表示最大亮度。
RGB 數據表示一個圖像的顏色信息,通常以矩陣的形式存儲。每個像素由一個或多個字節組成,其中每個字節對應一個顏色分量。在常見的圖像文件格式中,像素的存儲順序通常是連續的,按行或按列排列。
以下是一個簡單的示例,展示了一個 3x3 的圖像的 RGB 數據:
| R0 G0 B0 | R1 G1 B1 | R2 G2 B2 |
| R3 G3 B3 | R4 G4 B4 | R5 G5 B5 |
| R6 G6 B6 | R7 G7 B7 | R8 G8 B8 |
這里,每組 R G B
表示一個像素的紅、綠、藍三個分量的值。在實際應用中,圖像的大小可能是數百乃至數千像素,而 RGB 數據的表示會更加龐大。
在編程中,處理 RGB 數據通常需要使用專門的圖像處理庫,例如 OpenCV(Open Source Computer Vision Library)等。這些庫提供了豐富的函數和工具,方便開發者對圖像進行處理、分析和操作。
BMP(Bitmap)是一種位圖圖像文件格式,它是一種無損壓縮的圖像格式,通常以.bmp
為文件擴展名。BMP 文件格式最初由Microsoft開發,用于Windows平臺。
六、BMP 圖像以像素矩陣的形式存儲
BMP 圖像以像素矩陣的形式存儲,每個像素可以用來表示圖像中的一個點,而每個點的顏色信息則通過RGB(Red, Green, Blue)三個分量來表示。BMP 文件格式支持不同的顏色深度,包括1位、4位、8位、16位、24位和32位等多種格式。
BMP 文件的結構包括文件頭和圖像數據兩個主要部分:
-
文件頭(Bitmap File Header): 包含了文件的一些基本信息,比如文件類型、文件大小、圖像的偏移等。
-
信息頭(Bitmap Information Header): 包含了關于圖像的詳細信息,如圖像的寬度、高度、顏色平面數、每像素比特數等。
-
顏色表(Color Table): 針對使用調色板的圖像,包含了調色板中的顏色信息。
-
圖像數據: 包含了圖像的實際像素數據。
BMP 文件通常比較簡單,易于理解和解析。然而,由于它不使用壓縮算法,因此可能占用較大的存儲空間,尤其是對于彩色圖像。在實際應用中,更常見的圖像格式如JPEG、PNG等采用了更高效的壓縮算法。
常見的圖像格式
有許多不同的圖像格式,每種格式都有其特定的用途和優勢。以下是一些常見的圖像格式:
-
JPEG(Joint Photographic Experts Group): 一種有損壓縮格式,適用于照片和真彩圖像。它通過犧牲一些圖像細節來實現更小的文件大小。
-
PNG(Portable Network Graphics): 一種無損壓縮格式,適用于圖標、圖形和帶有透明背景的圖像。PNG支持多種顏色深度和透明度。
-
GIF(Graphics Interchange Format): 一種支持動畫和透明度的格式。GIF適用于簡單的圖形,但由于其有限的顏色深度,不適用于照片。
-
BMP(Bitmap): 一種無損格式,適用于簡單的圖像。BMP文件通常較大,因為它們未經壓縮。
-
TIFF(Tagged Image File Format): 一種靈活的格式,適用于存儲高質量的圖像和照片。TIFF支持無損壓縮和多頁文檔。
-
WEBP: 由Google開發的一種圖像格式,支持有損和無損壓縮,同時具有較小的文件大小。
-
SVG(Scalable Vector Graphics): 一種矢量圖形格式,適用于圖標和圖形。SVG圖像可縮放而不失真。
-
RAW: 一種未經處理的圖像格式,通常由數碼相機生成。RAW格式保留了更多的圖像信息,但文件較大。
-
ICO(Icon): 用于存儲圖標的格式,通常用于Windows應用程序。
這只是一小部分常見的圖像格式,實際上還有許多其他專用格式和變種,每種都適用于不同的用途。選擇圖像格式時,通常要考慮圖像的內容、用途、質量和文件大小。
七、Base64數據格式轉換
Base64是一種將二進制數據編碼成ASCII字符串的方法,通常用于在文本協議中傳輸二進制數據。你可以使用Base64編碼工具對圖像進行編碼,以下是一個示例:
base64 test.jpg > test_base64.txt
這將把 test.jpg
圖像文件編碼為Base64,并將結果保存到 test_base64.txt
文件中。
如果你想要將Base64字符串解碼回二進制數據,可以使用以下命令:
base64 -d test_base64.txt > test_decoded.jpg
這將從 test_base64.txt
文件中讀取Base64字符串并將其解碼為 test_decoded.jpg
圖像文件。
請注意,Base64編碼會增加數據的大小,因為它將二進制數據轉換為文本形式。在網絡傳輸中使用它可以確保數據以文本的形式傳遞,但需要考慮到編碼和解碼的性能開銷。
常用的Base64加密解密工具網站
一些常用的Base64加密解密工具網站包括:
- Base64 編碼解碼 - 在線工具
- Online Base64 編碼解碼
- Base64 編碼/解碼工具
請記住在使用在線工具時要謹慎,特別是在處理敏感數據時,因為在線服務可能會記錄你的數據。如果你處理敏感信息,請盡量使用本地工具。
八、加入圖片base64編碼
Base64是網絡上最常見的用于傳輸8Bit字節碼的編碼方式之一,可用于在HTTP環境下傳遞較長的標識信息。
在Linux下生成圖片的base64編碼
base64 test.jpg
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>char* getBase64FromFile(const char* filePath)
{char cmd[256] = {'\0'};char* base64Buf = NULL;// 使用安全的方式構建命令snprintf(cmd, sizeof(cmd), "base64 %s | tr -d '\n' > tmpFile", filePath);//圖片的base64流導入到文件中if (system(cmd) == -1) {perror("Error executing system command");return NULL;}int fd = open("./tmpFile", O_RDWR);if (fd == -1) {perror("Error opening file");return NULL;}// 計算文件大小int fileLen = lseek(fd, 0, SEEK_END);lseek(fd, 0, SEEK_SET);// 動態分配內存base64Buf = (char*)malloc(fileLen + 1);if (base64Buf == NULL) {perror("Error allocating memory");close(fd);return NULL;}memset(base64Buf, '\0', fileLen + 1);// 讀取文件內容到字符串(base64流)if (read(fd, base64Buf, fileLen) == -1) {perror("Error reading file");free(base64Buf);close(fd);return NULL;}close(fd);// 刪除臨時文件if (remove("tmpFile") == -1) {perror("Error deleting temporary file");}return base64Buf;
}int main() {const char* filePath = "your_file_path_here";char* base64String = getBase64FromFile(filePath);if (base64String != NULL) {printf("Base64 String:\n%s\n", base64String);// 釋放動態分配的內存free(base64String);}return 0;
}
九、人臉識別完整代碼及功能點實現現象
ocr.c
#include <stdio.h>
#include <curl/curl.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>// 定義bool類型和常量
typedef unsigned int bool; // 數據類型別名用typedef
#define true 1
#define false 0char ocrReturnBuf[1024] = {'\0'}; // 全局變量,用來接收從OCR后臺返回的數據// 回調函數,讀取從OCR后臺返回的數據(把從后臺的數據拷貝給ocrReturnBuf)
size_t readData(void *ptr, size_t size, size_t nmemb, void *stream)
{size_t totalSize = size * nmemb;// 為了避免溢出,計算實際拷貝的長度size_t copySize = (totalSize < (sizeof(ocrReturnBuf) - 1)) ? totalSize : (sizeof(ocrReturnBuf) - 1);// 拷貝數據到 ocrRetBuf 中memcpy(ocrReturnBuf, ptr, copySize);// 手動添加字符串終結符ocrReturnBuf[copySize] = '\0';return totalSize;
}char *getBase64FromFile(const char *filePath)
{char cmd[256] = {'\0'};char *base64Buf = NULL;// 使用安全的方式構建命令snprintf(cmd, sizeof(cmd), "base64 %s | tr -d '\n' > tmpFile", filePath);if (system(cmd) == -1) {perror("Error executing system command");return NULL;}int fd = open("./tmpFile", O_RDWR);if (fd == -1) {perror("Error opening file");return NULL;}// 計算文件大小int fileLen = lseek(fd, 0, SEEK_END);lseek(fd, 0, SEEK_SET);// 動態分配內存base64Buf = (char *)malloc(fileLen + 1);if (base64Buf == NULL) {perror("Error allocating memory");close(fd);return NULL;}memset(base64Buf, '\0', fileLen + 1);// 讀取文件內容到字符串if (read(fd, base64Buf, fileLen) == -1) {perror("Error reading file");free(base64Buf);close(fd);return NULL;}close(fd);// 刪除臨時文件if (remove("tmpFile") == -1) {perror("Error deleting temporary file");}return base64Buf;
}// 根據文檔,接口調用方法為post請求
bool postUrl()
{CURL *curl;CURLcode res;// 根據翔云平臺的接口要求 分開定義,然后字符串拼接char *img1 = getBase64FromFile("/home/orangepi/smart_home/test/test1_JPEG.webp"); // 圖片base64流char *img2 = getBase64FromFile("/home/orangepi/smart_home/test/test2_JPEG.webp");char *key = "JFD5c1iBh9LVqPkkZMxxxx";char *secret = "76f444813fc945bd9543e4d7e086xxxx";int typeId = 21;char *format = "xml";int len = strlen(key) + strlen(secret) + strlen(img1) + strlen(img2) + 128; // 分配空間不夠會>導致棧溢出char* postString = (char*)malloc(len);memset(postString, '\0', len);//因為postString是一個指針,不能用sizeof來計算其指向的大小// 字符串拼接sprintf(postString, "img1=%s&img2=%s&key=%s&secret=%s&typeId=%d&format=%s", img1, img2, key, secret, typeId, format);curl = curl_easy_init();if (curl){// 指定cookie緩存文件// if (curl_easy_setopt(curl, CURLOPT_COOKIEFILE, "/tmp/cookie.txt") != CURLE_OK)// {// fprintf(stderr, "Failed to set cookie file\n");// return false; // 在設置失敗時,直接返回// }// 指定post傳輸內容,get請求將URL和postString一次性發送curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postString);// 指定urlcurl_easy_setopt(curl, CURLOPT_URL, "https://netocr.com/api/faceliu.do");// 回調函數讀取返回值curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, readData);// 執行請求res = curl_easy_perform(curl);if (res != CURLE_OK) {fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));// 處理錯誤return false;}//字符串檢索 判斷翔云后臺返回的一大堆字符串中有沒有“否”if (strstr(ocrReturnBuf,"否") != NULL) { printf("不是同一個人\n");}else{printf("是同一個人\n");}// 清理資源curl_easy_cleanup(curl);}// 釋放動態分配的內存free(img1);free(img2);free(postString);return true;
}int main(void)
{postUrl();return 0;
}
編譯
gcc ocr.c -I /home/orangepi/curl-7.71.1/_install/include/ -L /home/orangepi/curl-7.71.1/_install/lib/ -lcurl
運行