【圖片識別改名】如何批量識別大量圖片的文字并重命名圖片,基于WPF和京東OCR識別接口的實現方案

應用場景

在企業文檔管理、數字圖書館、電商商品管理等場景中,經常需要處理大量圖片中的文字信息。例如:

  • 電商平臺需要將商品圖片中的型號、規格等信息提取出來作為文件名
  • 圖書館需要將掃描的圖書頁面識別為文字并整理歸檔
  • 企業需要將紙質文檔電子化并按內容分類

使用 WPF 和京東 OCR 接口可以開發一個高效的桌面應用程序JD圖片文字識別與重命名工具,實現圖片文字識別和批量重命名功能。

界面設計

一個功能完善的圖片文字識別與重命名工具界面應包含以下元素:

  1. 文件選擇區域:支持拖放或點擊選擇圖片文件 / 文件夾
  2. 處理隊列顯示:展示待處理和已處理的圖片列表
  3. OCR 配置區域:設置識別語言、API 參數等
  4. 重命名規則設置:自定義文件名格式和替換規則
  5. 處理進度顯示:實時展示處理進度和狀態
  6. 日志輸出區域:記錄處理過程和錯誤信息

下面是一個基于 WPF 的實現方案:

image-ocr-rename-wpf基于WPF和京東OCR的圖片文字識別與重命名工具

<Window x:Class="ImageOcrRenameTool.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"Title="JD圖片文字識別與重命名工具" Height="700" Width="900"WindowStartupLocation="CenterScreen"><Grid><Grid.RowDefinitions><RowDefinition Height="Auto"/><RowDefinition Height="Auto"/><RowDefinition Height="Auto"/><RowDefinition Height="*"/><RowDefinition Height="Auto"/></Grid.RowDefinitions><!-- 標題區域 --><Border Background="#3498db" Padding="10"><TextBlock Text="JD圖片文字識別與重命名工具" FontSize="20" FontWeight="Bold" Foreground="White"/></Border><!-- 文件選擇區域 --><GroupBox Header="文件選擇" Grid.Row="1" Margin="10" Padding="10"><Grid><Grid.ColumnDefinitions><ColumnDefinition Width="*"/><ColumnDefinition Width="Auto"/><ColumnDefinition Width="Auto"/></Grid.ColumnDefinitions><TextBox x:Name="txtFilePath" TextWrapping="Wrap" Margin="0,0,5,0" IsReadOnly="True"/><Button x:Name="btnSelectFile" Content="選擇文件" Margin="5,0" Padding="10,5" Click="BtnSelectFile_Click"/><Button x:Name="btnSelectFolder" Content="選擇文件夾" Margin="5,0" Padding="10,5" Click="BtnSelectFolder_Click" Grid.Column="2"/></Grid></GroupBox><!-- OCR配置區域 --><GroupBox Header="JD_OCR配置" Grid.Row="2" Margin="10" Padding="10"><Grid><Grid.RowDefinitions><RowDefinition Height="Auto"/><RowDefinition Height="Auto"/><RowDefinition Height="Auto"/></Grid.RowDefinitions><Grid.ColumnDefinitions><ColumnDefinition Width="Auto"/><ColumnDefinition Width="*"/><ColumnDefinition Width="Auto"/><ColumnDefinition Width="*"/></Grid.ColumnDefinitions><TextBlock Text="AppKey:" VerticalAlignment="Center" Margin="0,5"/><TextBox x:Name="txtAppKey" TextWrapping="Wrap" Margin="5,5" Text="{Binding AppKey, Mode=TwoWay}"/><TextBlock Text="AppSecret:" VerticalAlignment="Center" Margin="0,5" Grid.Column="2"/><TextBox x:Name="txtAppSecret" TextWrapping="Wrap" Margin="5,5" Text="{Binding AppSecret, Mode=TwoWay}"Grid.Column="3"/><TextBlock Text="識別語言:" VerticalAlignment="Center" Margin="0,5" Grid.Row="1"/><ComboBox x:Name="cmbLanguage" Margin="5,5" Grid.Row="1" Grid.Column="1"ItemsSource="{Binding AvailableLanguages}" SelectedItem="{Binding SelectedLanguage, Mode=TwoWay}"/><TextBlock Text="重命名規則:" VerticalAlignment="Center" Margin="0,5" Grid.Row="2"/><TextBox x:Name="txtRenameRule" TextWrapping="Wrap" Margin="5,5" Grid.Row="2" Grid.Column="1"Text="{Binding RenameRule, Mode=TwoWay}" ToolTip="使用{text}表示識別的文字,{index}表示序號,{original}表示原文件名"/></Grid></GroupBox><!-- 處理區域 --><GroupBox Header="處理隊列" Grid.Row="3" Margin="10" Padding="10"><Grid><Grid.RowDefinitions><RowDefinition Height="Auto"/><RowDefinition Height="*"/></Grid.RowDefinitions><StackPanel Orientation="Horizontal" Margin="0,0,0,5"><Button x:Name="btnStartProcess" Content="開始處理" Padding="10,5" Click="BtnStartProcess_Click" IsEnabled="{Binding CanStartProcessing}"/><Button x:Name="btnStopProcess" Content="停止處理" Padding="10,5" Margin="5,0,0,0" Click="BtnStopProcess_Click" IsEnabled="{Binding IsProcessing}"/><ProgressBar x:Name="progressBar" Width="200" Height="20" Margin="10,0,0,0" Value="{Binding ProgressValue}" Maximum="{Binding ProgressMax}"/><TextBlock x:Name="txtProgress" Text="{Binding ProgressText}" VerticalAlignment="Center" Margin="5,0,0,0"/></StackPanel><DataGrid x:Name="dataGrid" AutoGenerateColumns="False" ItemsSource="{Binding ImageItems}" CanUserAddRows="False" CanUserDeleteRows="False" SelectionMode="Single"HorizontalGridLinesBrush="LightGray" VerticalGridLinesBrush="LightGray"><DataGrid.Columns><DataGridTextColumn Header="序號" Binding="{Binding Index}" Width="50"/><DataGridTextColumn Header="原文件名" Binding="{Binding OriginalFileName}" Width="*"/><DataGridTextColumn Header="識別文字" Binding="{Binding RecognizedText}" Width="*"/><DataGridTextColumn Header="新文件名" Binding="{Binding NewFileName}" Width="*"/><DataGridTextColumn Header="狀態" Binding="{Binding Status}" Width="100"/></DataGrid.Columns></DataGrid></Grid></GroupBox><!-- 日志區域 --><GroupBox Header="處理日志" Grid.Row="4" Margin="10" Padding="10"><TextBox x:Name="txtLog" TextWrapping="Wrap" AcceptsReturn="True" IsReadOnly="True" VerticalScrollBarVisibility="Auto" Height="100"/></GroupBox></Grid>
</Window>    

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Input;namespace ImageOcrRenameTool
{public class MainViewModel : INotifyPropertyChanged{private readonly JdOcrService _ocrService;private string _appKey;private string _appSecret;private string _selectedLanguage = "CHN_ENG";private string _renameRule = "{text}_{index}";private bool _isProcessing;private double _progressValue;private double _progressMax;private string _progressText = "就緒";public event PropertyChangedEventHandler PropertyChanged;public ObservableCollection<ImageItem> ImageItems { get; } = new ObservableCollection<ImageItem>();public List<string> AvailableLanguages { get; } = new List<string>{"CHN_ENG", "ENG", "JAP", "KOR", "FRE", "SPA", "POR", "GER", "ITA", "RUS"};public string AppKey{get => _appKey;set{_appKey = value;OnPropertyChanged();}}public string AppSecret{get => _appSecret;set{_appSecret = value;OnPropertyChanged();}}public string SelectedLanguage{get => _selectedLanguage;set{_selectedLanguage = value;OnPropertyChanged();}}public string RenameRule{get => _renameRule;set{_renameRule = value;OnPropertyChanged();}}public bool IsProcessing{get => _isProcessing;set{_isProcessing = value;OnPropertyChanged();OnPropertyChanged(nameof(CanStartProcessing));}}public bool CanStartProcessing => !IsProcessing && ImageItems.Any();public double ProgressValue{get => _progressValue;set{_progressValue = value;OnPropertyChanged();}}public double ProgressMax{get => _progressMax;set{_progressMax = value;OnPropertyChanged();}}public string ProgressText{get => _progressText;set{_progressText = value;OnPropertyChanged();}}public MainViewModel(){_ocrService = new JdOcrService();}public void AddImageFiles(string[] filePaths){if (filePaths == null || !filePaths.Any())return;var supportedExtensions = new[] { ".jpg", ".jpeg", ".png", ".bmp", ".gif" };foreach (var filePath in filePaths){if (File.Exists(filePath) && supportedExtensions.Contains(Path.GetExtension(filePath).ToLower())){var index = ImageItems.Count + 1;ImageItems.Add(new ImageItem{Index = index,FilePath = filePath,OriginalFileName = Path.GetFileName(filePath)});}}ProgressMax = ImageItems.Count;OnPropertyChanged(nameof(CanStartProcessing));}public void AddImageFolder(string folderPath){if (string.IsNullOrEmpty(folderPath) || !Directory.Exists(folderPath))return;var supportedExtensions = new[] { ".jpg", ".jpeg", ".png", ".bmp", ".gif" };var filePaths = Directory.GetFiles(folderPath).Where(f => supportedExtensions.Contains(Path.GetExtension(f).ToLower())).ToList();AddImageFiles(filePaths.ToArray());}public async Task ProcessImagesAsync(CancellationToken cancellationToken){IsProcessing = true;ProgressValue = 0;try{if (string.IsNullOrEmpty(AppKey) || string.IsNullOrEmpty(AppSecret)){throw new InvalidOperationException("請先設置京東OCR的AppKey和AppSecret");}_ocrService.Initialize(AppKey, AppSecret);var processedCount = 0;foreach (var item in ImageItems){if (cancellationToken.IsCancellationRequested)throw new OperationCanceledException();try{item.Status = "處理中";ProgressText = $"正在處理: {item.OriginalFileName}";// 執行OCR識別var ocrResult = await _ocrService.RecognizeImageAsync(item.FilePath, SelectedLanguage, cancellationToken);item.RecognizedText = ocrResult;// 生成新文件名item.NewFileName = GenerateNewFileName(item, processedCount + 1);// 重命名文件RenameFile(item);item.Status = "已完成";processedCount++;}catch (OperationCanceledException){item.Status = "已取消";throw;}catch (Exception ex){item.Status = "失敗";item.ErrorMessage = ex.Message;}finally{ProgressValue++;ProgressText = $"已完成: {processedCount}/{ImageItems.Count}";}}ProgressText = $"處理完成! 共處理 {processedCount} 個文件";}finally{IsProcessing = false;}}private string GenerateNewFileName(ImageItem item, int index){if (string.IsNullOrEmpty(RenameRule))return item.OriginalFileName;var originalName = Path.GetFileNameWithoutExtension(item.OriginalFileName);var extension = Path.GetExtension(item.OriginalFileName);// 替換模板變量var newName = RenameRule.Replace("{text}", SanitizeFileName(item.RecognizedText)).Replace("{index}", index.ToString()).Replace("{original}", originalName);// 確保文件名不超過最大長度if (newName.Length > 240) // NTFS文件名最大長度為255字符,留出空間給擴展名newName = newName.Substring(0, 240);return newName + extension;}private void RenameFile(ImageItem item){if (string.IsNullOrEmpty(item.NewFileName) || item.NewFileName == item.OriginalFileName)return;var directory = Path.GetDirectoryName(item.FilePath);if (string.IsNullOrEmpty(directory))return;var newFilePath = Path.Combine(directory, item.NewFileName);try{// 如果新文件名已存在,添加序號if (File.Exists(newFilePath)){var baseName = Path.GetFileNameWithoutExtension(item.NewFileName);var extension = Path.GetExtension(item.NewFileName);var counter = 1;do{newFilePath = Path.Combine(directory, $"{baseName}_{counter}{extension}");counter++;} while (File.Exists(newFilePath));item.NewFileName = Path.GetFileName(newFilePath);}File.Move(item.FilePath, newFilePath);item.FilePath = newFilePath;}catch (Exception ex){throw new Exception($"重命名文件失敗: {ex.Message}");}}private string SanitizeFileName(string fileName){if (string.IsNullOrEmpty(fileName))return "未識別文字";// 移除或替換文件路徑中的非法字符var invalidChars = Path.GetInvalidFileNameChars();var sanitized = new string(fileName.Select(c => invalidChars.Contains(c) ? '_' : c).ToArray());// 替換連續的空格和下劃線sanitized = Regex.Replace(sanitized, @"[_\s]+", "_");// 去除首尾空格和下劃線return sanitized.Trim('_', ' ');}protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null){PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));}}
}    

詳細代碼步驟

這個應用程序主要包含以下幾個部分:

  1. 界面設計:使用 WPF 創建了一個直觀的用戶界面,包括文件選擇、OCR 配置、處理隊列和日志顯示等區域。

  2. 數據模型

    • ImageItem類:表示待處理的圖片項,包含原始文件名、識別文字、新文件名和處理狀態等屬性
    • JdOcrResponse系列類:用于解析京東OCR接口的返回數據
  3. 視圖模型MainViewModel類實現了主要的業務邏輯:

    • 管理圖片文件列表
    • 與京東 OCR 服務交互
    • 生成新文件名并執行重命名操作
    • 管理處理進度和狀態
  4. OCR 服務JdOcrService類封裝了與京東OCR API的通信:

    • 初始化 API 憑證
    • 將圖片轉換為 Base64 格式
    • 發送請求并解析響應
  5. 文件名處理:實現了安全的文件名生成和清理邏輯,確保生成的文件名符合文件系統規則。

總結優化

這個應用程序提供了一個功能完整的圖片文字識別與重命名解決方案,但還有一些可以優化的地方:

  1. 性能優化

    • 可以實現多線程處理,提高大量圖片的處理速度
    • 添加圖片緩存機制,避免重復處理相同圖片
    • 實現斷點續傳功能,支持中斷后繼續處理
  2. 錯誤處理

    • 增強對網絡異常的處理,實現自動重試機制
    • 提供更詳細的錯誤日志和調試信息
    • 添加文件沖突解決策略選項
  3. 擴展功能

    • 支持更多 OCR 服務提供商,實現服務切換功能
    • 添加圖片預處理功能,如旋轉、裁剪、增強對比度等
    • 支持導出識別結果到文本文件或 Excel 表格

這個應用程序可以根據實際需求進一步定制和擴展,成為一個強大的圖片文字處理工具。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/85067.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/85067.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/85067.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

簡歷模板2——數據挖掘工程師5年經驗

姓名 / Your Name 數據挖掘工程師 | 5年經驗 | 推薦/風控/圖模型 &#x1f4de; 138-XXXX-XXXX | ?? your.emailexample.com | &#x1f310; github.com/yourname | &#x1f4cd; 北京 &#x1f3af; 個人簡介 / Summary 5年大廠數據挖掘經驗&#xff0c;碩士學歷。擅長推…

CSS3 漸變效果

1. 引言 CSS3 漸變能夠在指定顏色之間創建平滑過渡效果。這種設計元素不僅能為網頁增添豐富的視覺層次&#xff0c;更是現代網頁設計的重要組成部分。CSS3 提供兩種主要的漸變類型&#xff1a;線性漸變(Linear Gradient) - 沿直線方向進行顏色過渡&#xff1b;徑向漸變(Radial…

A Survey on 3D Gaussian Splatting——3D高斯領域綜述

原文鏈接&#xff1a;[2401.03890] A Survey on 3D Gaussian Splatting 動態更新的GitHub倉庫&#xff08;包含性能對比與最新文獻追蹤&#xff09;&#xff1a; https://github.com/guikunchen/3DGS-Benchmarks https://github.com/guikunchen/Awesome3DGS 摘要&#xff1…

計算機網絡 期末實訓 eNSP 校園網

eNSP 綜合實訓 小型校園網 計算機網絡期末實訓 01 搭建拓撲 1.設計任務 構建一個小型校園網絡,涵蓋以下設備與區域: 學生宿舍區:50臺計算機辦公樓區:30臺計算機(細分為財務部門、人事部門及其他科室)圖書館:10臺計算機教學樓:30臺計算機服務器集群:2臺服務器,分別用…

Smart Form Adobe form 強制更改內表:TNAPR

強制更改內表:TNAPR se16-> Smart Form總覽 Smart form 變量格式說明: &symbol& (括號中,小寫字母為變量) &symbol& 屏蔽從第一位開始的N位 &symbol (n)& 只顯示前N位 &symbol (S)& 忽略正負號 &symbol (<)& 符號在…

頁面配置文件pages.json和小程序配置

頁面配置文件pages.json和小程序配置 pages.jsonpagesstyle-navigationBarBackgroundColorstyle-navigationBarTitleTextstyle-navigationStylestyle-enablePullDownRefresh注意事項不同平臺區分配置新建頁面 globalStyletabBar代碼 manifest.json授權web配置代理 pages.json …

Linux網絡配置工具ifconfig與ip命令的全面對比

在Linux網絡管理中&#xff0c;ifconfig和 ip命令是最常用的兩個工具。隨著時間的推移&#xff0c;ip命令逐漸取代了 ifconfig&#xff0c;成為更強大和靈活的網絡配置工具。本文將對這兩個工具進行全面對比&#xff0c;幫助您理解它們的區別和各自的優勢。 一、ifconfig命令 …

STM32 實現解析自定義協議

一、環形隊列設計與實現&#xff08;核心緩沖機制&#xff09; 數據結構設計&#xff1a; #define BUFFER_SIZE 512 #define BUFFER_MASK (BUFFER_SIZE - 1) typedef struct {volatile uint8_t buffer[BUFFER_SIZE]; // 環形緩沖區&#xff08;大小可配置&#xff09;volati…

NGINX 四層上游模塊`ngx_stream_upstream_module` 實戰指南

一、模塊定位與引入 模塊名稱&#xff1a;ngx_stream_upstream_module 首次引入&#xff1a;NGINX 1.9.0&#xff08;2015-08-04&#xff09; 編譯選項&#xff1a;啟用 --with-stream&#xff08;含此模塊&#xff09; 作用&#xff1a; 定義后端服務器組&#xff08;upstr…

WinUI3入門2:DataGrid動態更新 添加刪除和修改字段

初級代碼游戲的專欄介紹與文章目錄-CSDN博客 我的github&#xff1a;codetoys&#xff0c;所有代碼都將會位于ctfc庫中。已經放入庫中我會指出在庫中的位置。 這些代碼大部分以Linux為目標但部分代碼是純C的&#xff0c;可以在任何平臺上使用。 源碼指引&#xff1a;github源…

基于Python學習《Head First設計模式》第十三章 現實世界中的模式

定義設計模式 設計模式要素 模式名稱、分類意圖&#xff1a;描述模式是什么動機&#xff1a;描述什么時候使用這個模式&#xff0c;具體場景適用性&#xff1a;描述什么地方使用這個模式&#xff0c;用在什么場合結構&#xff1a;類圖參與者&#xff1a;類和對象的責任和角色…

線性代數(1)線性方程組的多種解法

求解線性方程組是線性代數的核心問題之一&#xff0c;根據方程組的類型&#xff08;如齊次/非齊次、方陣/非方陣、稀疏/稠密等&#xff09;&#xff0c;可以采用不同的解法。以下是常見的線性方程組解法分類及簡要說明&#xff1a; 一、直接解法&#xff08;精確解&#xff09…

肝臟/肝臟腫瘤圖像分割數據集(貓臉碼客第261期)

探秘肝臟/肝臟腫瘤圖像分割&#xff1a;醫學影像技術的新突破 一、引言 肝臟/肝臟腫瘤圖像分割在醫學領域占據著愈發重要的地位&#xff0c;為肝臟疾病的精準診斷與有效治療提供了關鍵技術支撐。隨著醫學成像技術的飛速進步&#xff0c;如磁共振成像&#xff08;MRI&#xff…

【LLM05---位置編碼】

文章目錄 位置編碼引出Transformer中位置編碼方法:Sinusoidal functions兩個重要性質位置編碼 最近在學習位置編碼,想找一個講的比較透徹的文章或視頻,找了半天,滿意的一個也沒有,所以自己記錄一下。 注意,本篇筆記只作為自己的學習記錄用,更好的講解的內容請看鏈接:位…

pikachu——ssrf

概念補充&#xff1a; 內網&#xff1a;局部范圍內的私有網絡&#xff0c;比如局域網就是一個小范圍的內網&#xff0c;有私有IP&#xff0c;并且內網受防火墻的保護&#xff0c;外網無法直接訪問 外網&#xff1a;全球范圍的公共網絡&#xff0c;公有ip ip地址&#xff1a;…

java 設計模式_行為型_13備忘錄模式

13.備忘錄模式 模式定義 備忘錄模式&#xff08;Memento Pattern&#xff09;模式的定義&#xff1a;在不破壞封裝性的前提下&#xff0c;捕獲一個對象的內部狀態&#xff0c;并在該對象之外保存這個狀態&#xff0c;以便以后當需要時能將該對象恢復到原先保存的狀態。該模式又…

創建postgres數據庫失敗

異常&#xff1a; postgres# CREATE DATABASE deepflow_agent2; ERROR: source database "template1" is being accessed by other users DETAIL: There are 2 other sessions using the database 如何斷聯這兩個session 要解決 PostgreSQL 中因 template1 數據庫…

臥安機器人闖上市:深耕AI具身技術,“大疆教父”李澤湘再落子

撰稿|行星 來源|貝多財經 又一家機器人企業&#xff0c;現身港股資本市場。貝多財經了解到&#xff0c;臥安機器人&#xff08;深圳&#xff09;股份有限公司&#xff08;下稱“臥安機器人”&#xff09;于6月8日向港交所提交了上市申請&#xff0c;國泰君安國際、華泰國際為…

基于GNU Radio Companion搭建的AM信號實驗

目錄 實驗目的和要求 1、AM收發系統仿真和實際接收 調制過程 2、Lab 2.1實驗過程AM信號的產生 AM信號的表達式 調制深度的概念 3、Lab2.2 AM信號的解調 4、Lab2.3 實際用RTLSDR接收一個ISM(912MHz)頻率的AM信號,信號的AM調制為音頻為48KHz的音樂信號 實驗目的和要求 …

【go】(僅思路)使用go實現一款簡單的關系型數據庫gosql

文章目錄 背景給navicate回復版本號建立連接數據庫list新建數據庫刪除數據庫刪除表查詢表數據總結roadmapnavicate連接適配 背景 使用go很容易編譯出一個二進制文件&#xff0c;已經有人用純go實現了sqlite3的驅動&#xff08;go get github.com/glebarez/sqlite&#xff09;&…