簡體   English   中英

Celery + Redis 用於多處理

[英]Celery + Redis for multiprocessing

我使用 tesseract、openCV 和 Google Vision 構建了一個用於光學字符識別的應用程序。 我有 4 種可用的文件類型可供識別(如收據)。 因此用戶可以選擇文件(圖像),然后選擇文檔的確切類型並單擊“識別”。 會發生這樣一個過程:

  1. 圖像 Alignment 和 openCV:我們為每種文檔類型提供示例圖像。 例如,當用戶選擇類型 A 時,openCV 找到類型 A 的示例圖像並開始搜索相似性。 當找到足夠的相似元素時,openCV 會對齊用戶的圖像文件以達到最大相似度。 function 的結果 - 返回對齊圖像的路徑。
  2. 使用 tesseract 進行驗證:在 alignment 之后,tesseract 打開之前對齊的圖像並識別它。 然后我有一個單詞列表,它必須在已識別的文本中,因此我們開始檢查已識別的文本,並且對於每個成功的置信度,我們都會增加我們的驗證計數器。 所以最后,如果我們的驗證計數器 > 一定數量,我們批准結果並認為圖像文件是正確的,谷歌可以在下一步中識別它。 如果驗證計數器不足以批准,我們將文檔類型設置為無 object。 function 的結果 - 返回已批准的對齊圖像的路徑和用戶在開始時選擇的文檔類型。
  3. 在此之后,我們開始最終的 function。 如果文檔類型不是無(這意味着我們有一個批准的圖像文件),我們將此圖像路徑傳遞給 function,它將使用 Google Vision API 進行識別,然后我們得到一個 .txt 文件。

所以這是常見的場景。 但是我也提供給用戶選擇文檔的類型,叫做“我不知道類型”;)而function,選擇了這種類型后執行,只是經過for循環(遍歷所有類型我們擁有的文件)。 因此,當我們每次使用 openCV+Tesseract 完成工作時都返回我們的文檔類型,很明顯我們只會得到一個非 None 類型,這將是正確的,我們將使用它來識別。 所以這個 function 的執行時間最長,因為我們需要補足 4 個 openCV 對齊和最多 4 個 tesseract 識別才能找到合適的文檔類型。 我想通過為這個特定的 function 實現多處理來加速我的程序。 我決定為這些目的使用 Celery+Redis。 這個想法是:

  1. 將此循環 function 設置為 Celery 任務。
  2. 等待所有操作完成。
  3. 從 redis 讀取響應(必須有 4 個響應,其中 3 個是 NoneType,其中 1 個是真實的 Document Type)。
  4. 清潔 redis。
  5. 在最終的 Google function 中使用正確的類型。

所以這些是我的功能,我在上面說過:

raw_img_path - 用戶使用 UI 選擇的路徑 dt - 用戶使用 UI 選擇的文檔類型

calc_receipt - 用於識別我們何時知道文檔類型:

def calc_receipt(self, raw_img_path, dt):
    aligned_img_path = OpenCV.align_img(
        template_path="some\\path\\for\\chosen\\type",
        raw_img_path="user\\image\\path",
        result_img_path="aligned\\image\\path",
    )

    tesseract_result = Tesseract.read_from_img(
        img_path="aligned\\image\\path",
    )

    if tesseract_result:
        return aligned_img_path, dt

    return '', DocumentType.NONE

calc_receipts - 用於識別我們何時不知道類型:

def calc_receipts(self, raw_img_path, selected_doc_type):

    for dt in map_receipt_to_receipts[selected_doc_type]:
        aligned_img_path, doc_type = self.calc_receipt(raw_img_path, dt)
        if doc_type is not DocumentType.NONE:
            return aligned_img_path, doc_type

可用類型列表:

map_receipt_to_receipts = {
    DocumentType.NONE: [],
    DocumentType.DONT_KNOW: [
        DocumentType.RESTAURANT,
        DocumentType.CAFE,
        DocumentType.BAR,
        DocumentType.COFFEE_SHOP,
    ],
    DocumentType.RESTAURANT: [
        DocumentType.RESTAURANT,
    ],
    DocumentType.CAFE: [
        DocumentType.CAFE,
    ],
    DocumentType.BAR: [
        DocumentType.BAR,
    ],
    DocumentType.COFFEE_SHOP: [
        DocumentType.COFFEE_SHOP,
    ],
}

class DocumentType 是為方便起見而制作的:

class DocumentType(EnumBase):
    NONE = 0
    DONT_KNOW = 1
    RESTAURANT = 2
    CAFE = 3
    BAR = 4
    COFFEE_SHOP = 5

據我所知,我需要重建 calc_receipts() function。 我有一些問題:

  1. 我應該從這個 function 開始 celery 工作人員嗎?
  2. 我可以從 Python 代碼而不是使用控制台啟動 celery 客戶端嗎?
  3. 如何管理 redis 響應並等待所有 4 個操作。
  4. 對於這種使用 Celery+Redis 的案例,您通常會推薦什么? 如果我的問題很愚蠢,我很抱歉,但我很難在 Web 中找到答案。 文檔不夠清晰,對初學者不夠友好。

A1: Celery worker 作為獨立進程啟動。 是的,您可以以編程方式啟動它,但這非常罕見(我使用它近 6 年,從未需要它)。 我想一旦您熟悉了 Celery,您就會發現最適合您的選擇。 直到你發現你真的需要以這種方式啟動它,我建議將它作為一個獨立的進程運行。 在生產中,您可能希望它作為系統服務。

A2:老實說,沒有“芹菜客戶端”之類的東西...... Celery 建立在受支持的代理提供的消息傳遞功能之上。 根據分布式生產者/消費者(或發布/訂閱)模式來考慮它。 如果“客戶端”的意思是“生產者” - 將消息(任務)發送到特定隊列(或使用最常見的默認隊列)的東西,那么是的,你可以通過編程方式做到這一點,事實上這就是我們大多數人都在這樣做。

A3:您不關心 Redis。 這完全是 Celery 的工作。 如果我理解你,你需要構建一個簡單的工作流,可能使用 Chord 原語(因為你需要等到所有任務都完成)。 為此,您需要熟悉Celery 工作流程

A4:我使用 Celery 和 Redis(實際上是 AWS ElastiCache)作為代理和結果后端。 我相信 Redis 可能是 Celery 最常用的代理,可能是因為它的設置和使用非常簡單。 Celery 文檔可能看起來不清楚,但它包含大量信息。 此外,您還有數以千計的博客文章描述了人們如何在各種情況下使用 Celery。 像往常一樣,從簡單的事情開始,少做工人,然后嘗試以分布式方式執行一些小任務。 我按照Celery 文檔的第一步學習了 Celery。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM