首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >如何批量识别图片文字并重命名,批量区域识别图片内容对图片改名,基于WPF和腾讯OCR的解决方案

如何批量识别图片文字并重命名,批量区域识别图片内容对图片改名,基于WPF和腾讯OCR的解决方案

原创
作者头像
不负众望
发布2025-03-26 15:54:42
发布2025-03-26 15:54:42
69700
代码可运行
举报
运行总次数:0
代码可运行

一、项目背景

在日常工作和生活中,我们常常需要处理大量的图片文件,这些图片可能包含重要的文字信息。手动识别这些文字并进行相应的处理(如重命名图片文件)既耗时又容易出错。为了解决这一问题,本项目旨在开发一个基于WPF(Windows Presentation Foundation)的桌面应用程序,结合腾讯OCR(光学字符识别)技术,实现批量识别图片中的文字并根据识别结果对图片进行重命名或区域内容识别后处理。

通过本项目,用户可以:

  • 批量上传图片文件。
  • 使用腾讯OCR API识别图片中的文字。
  • 根据识别的文字内容对图片进行重命名。
  • 支持选择特定区域进行内容识别,并基于区域内容进行处理。
  • 提高工作效率,减少手动操作的错误。

二、界面设计

WPF提供了丰富的UI组件和灵活的布局方式,适合构建功能强大且用户友好的桌面应用。以下是该应用的主要界面设计元素:

1. 主窗口布局

  • 菜单栏
    • 文件:打开图片文件夹、退出应用
    • 帮助:关于、帮助文档
  • 工具栏
    • 选择图片文件夹按钮
    • 开始识别按钮
    • 设置按钮(用于配置OCR参数)
  • 主内容区
    • 图片列表展示:显示已选择的图片缩略图,支持多选和删除。
    • OCR结果展示:显示每张图片的识别结果,支持手动编辑。
    • 进度条:显示当前操作进度。
    • 日志输出区:实时显示操作日志和错误信息。
  • 状态栏
    • 显示当前选中图片数量、已处理图片数量等信息。

2. 用户流程

  1. 用户通过菜单或工具栏选择包含图片的文件夹。
  2. 系统加载并展示图片列表。
  3. 用户可以选择全部或部分图片进行处理。
  4. 点击“开始识别”按钮,程序调用腾讯OCR API进行文字识别。
  5. 识别结果展示在界面上,用户可以查看和编辑。
  6. 根据识别结果,用户可以选择对图片进行重命名或其他操作。
  7. 系统完成所有操作后,显示处理结果和日志信息。

三、详细代码

1. 项目结构

代码语言:javascript
代码运行次数:0
运行
复制
ImageOCRRenamer/
├── ImageOCRRenamer/
│   ├── MainWindow.xaml
│   ├── MainWindow.xaml.cs
│   ├── OcrService.cs
│   ├── ImageProcessor.cs
│   ├── Models/
│   │   ├── ImageItem.cs
│   │   └── OcrResult.cs
│   ├── Services/
│   │   └── TencentOcrClient.cs
│   ├── Views/
│   │   └── ImageListView.xaml
│   └── App.xaml
├── Resources/
│   └── styles.xaml
└── packages.config

2. 主要代码实现

2.1 安装必要的NuGet包
  • TencentCloudSDKCSharp:腾讯云官方提供的.NET SDK,用于调用OCR API。
  • MahApps.Metro​(可选):用于美化WPF界面。
代码语言:javascript
代码运行次数:0
运行
复制
bashInstall-Package TencentCloudSDKCSharp
Install-Package MahApps.Metro
2.2 配置腾讯OCR API

首先,需要在腾讯云控制台开通OCR服务,并获取API密钥(SecretId和SecretKey)。

2.3 MainWindow.xaml
代码语言:javascript
代码运行次数:0
运行
复制
xml<Window x:Class="ImageOCRRenamer.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:ImageOCRRenamer"
        Title="图片OCR批量重命名工具" Height="600" Width="800">
    <Grid>
        <!-- 菜单栏 -->
        <Menu Grid.Row="0">
            <MenuItem Header="文件">
                <MenuItem Header="选择图片文件夹" Click="SelectFolder_Click"/>
                <MenuItem Header="退出" Click="Exit_Click"/>
            </MenuItem>
            <MenuItem Header="帮助">
                <MenuItem Header="关于"/>
                <MenuItem Header="帮助文档"/>
            </MenuItem>
        </Menu>

        <!-- 工具栏 -->
        <ToolBarTray Grid.Row="1">
            <ToolBar>
                <Button Content="选择图片文件夹" Click="SelectFolder_Click"/>
                <Button Content="开始识别" Click="StartRecognition_Click" IsEnabled="{Binding IsImagesSelected}"/>
            </ToolBar>
        </ToolBarTray>

        <!-- 图片列表展示 -->
        <ListView x:Name="ImageListView" Grid.Row="2" ItemsSource="{Binding ImageItems}" SelectionMode="Extended">
            <ListView.View>
                <GridView>
                    <GridViewColumn Header="缩略图" Width="100">
                        <GridViewColumn.CellTemplate>
                            <DataTemplate>
                                <Image Source="{Binding Thumbnail}" Width="80" Height="80"/>
                            </DataTemplate>
                        </GridViewColumn.CellTemplate>
                    </GridViewColumn>
                    <GridViewColumn Header="文件名" DisplayMemberBinding="{Binding FileName}" Width="200"/>
                    <GridViewColumn Header="识别状态" DisplayMemberBinding="{Binding Status}" Width="150"/>
                    <GridViewColumn Header="OCR结果" Width="300">
                        <GridViewColumn.CellTemplate>
                            <DataTemplate>
                                <TextBlock Text="{Binding OcrResult}" TextWrapping="Wrap"/>
                            </DataTemplate>
                        </GridViewColumn.CellTemplate>
                    </GridViewColumn>
                </GridView>
            </ListView.View>
        </ListView>

        <!-- 进度条 -->
        <ProgressBar x:Name="ProgressBar" Grid.Row="3" Height="25" Value="{Binding Progress}" Minimum="0" Maximum="100" Visibility="{Binding IsProcessing, Converter={StaticResource BooleanToVisibilityConverter}}"/>

        <!-- 日志输出 -->
        <TextBox x:Name="LogTextBox" Grid.Row="4" IsReadOnly="True" ScrollViewer.VerticalScrollBarVisibility="Auto" Height="100" VerticalAlignment="Bottom"/>
    </Grid>
</Window>
2.4 MainWindow.xaml.cs
代码语言:javascript
代码运行次数:0
运行
复制
csharpusing System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Windows;
using System.Windows.Controls;

namespace ImageOCRRenamer
{
    public partial class MainWindow : Window, INotifyPropertyChanged
    {
        private ObservableCollection<ImageItem> _imageItems;
        private bool _isProcessing;
        private int _progress;

        public ObservableCollection<ImageItem> ImageItems
        {
            get => _imageItems;
            set
            {
                _imageItems = value;
                OnPropertyChanged();
            }
        }

        public bool IsProcessing
        {
            get => _isProcessing;
            set
            {
                if (_isProcessing != value)
                {
                    _isProcessing = value;
                    OnPropertyChanged();
                    StartRecognitionButton.IsEnabled = !value;
                }
            }
        }

        public int Progress
        {
            get => _progress;
            set
            {
                _progress = value;
                OnPropertyChanged();
                ProgressBar.Value = value;
            }
        }

        public bool IsImagesSelected => ImageItems.Any(item => !string.IsNullOrEmpty(item.FilePath));

        public MainWindow()
        {
            InitializeComponent();
            DataContext = this;
            ImageItems = new ObservableCollection<ImageItem>();
        }

        private void SelectFolder_Click(object sender, RoutedEventArgs e)
        {
            var folderDialog = new System.Windows.Forms.FolderBrowserDialog();
            if (folderDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                string folderPath = folderDialog.SelectedPath;
                LoadImages(folderPath);
            }
        }

        private void LoadImages(string folderPath)
        {
            ImageItems.Clear();
            string[] files = Directory.GetFiles(folderPath, "*.*", SearchOption.AllDirectories)
                .Where(s => s.EndsWith(".png", StringComparison.OrdinalIgnoreCase) ||
                            s.EndsWith(".jpg", StringComparison.OrdinalIgnoreCase) ||
                            s.EndsWith(".jpeg", StringComparison.OrdinalIgnoreCase) ||
                            s.EndsWith(".bmp", StringComparison.OrdinalIgnoreCase)).ToArray();

            foreach (var file in files)
            {
                ImageItems.Add(new ImageItem
                {
                    FilePath = file,
                    FileName = Path.GetFileName(file),
                    Thumbnail = GenerateThumbnail(file)
                });
            }
        }

        private System.Windows.Media.Imaging.BitmapImage GenerateThumbnail(string filePath)
        {
            try
            {
                using (var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
                {
                    var bitmap = new System.Windows.Media.Imaging.BitmapImage();
                    bitmap.BeginInit();
                    bitmap.StreamSource = stream;
                    bitmap.CacheOption = System.Windows.Media.Imaging.BitmapCacheOption.OnLoad;
                    bitmap.EndInit();
                    bitmap.Freeze(); // 必须冻结以在UI线程外使用
                    return bitmap;
                }
            }
            catch
            {
                return null;
            }
        }

        private async void StartRecognition_Click(object sender, RoutedEventArgs e)
        {
            if (string.IsNullOrEmpty(Properties.Settings.Default.TencentSecretId) ||
                string.IsNullOrEmpty(Properties.Settings.Default.TencentSecretKey))
            {
                MessageBox.Show("请先配置腾讯云的SecretId和SecretKey!");
                return;
            }

            IsProcessing = true;
            Progress = 0;

            var ocrClient = new TencentOcrClient(Properties.Settings.Default.TencentSecretId, Properties.Settings.Default.TencentSecretKey);
            int total = ImageItems.Count;
            int processed = 0;

            foreach (var item in ImageItems)
            {
                try
                {
                    string result = await ocrClient.GeneralBasicOCR(item.FilePath);
                    item.OcrResult = result.Length > 100 ? result.Substring(0, 100) + "..." : result;
                    // 这里可以添加处理OCR结果并重命名文件的逻辑
                    // 例如:根据识别到的文字重命名文件
                    // string newName = ExtractNameFromOCR(result) + Path.GetExtension(item.FilePath);
                    // File.Move(item.FilePath, Path.Combine(Path.GetDirectoryName(item.FilePath), newName));
                }
                catch (Exception ex)
                {
                    item.Status = "识别失败: " + ex.Message;
                    Log("识别失败: " + item.FileName + " - " + ex.Message);
                }
                finally
                {
                    processed++;
                    Progress = (int)(((double)processed / total) * 100);
                }
            }

            IsProcessing = false;
            Log("所有图片已处理完成!");
        }

        private void Log(string message)
        {
            Dispatcher.Invoke(() =>
            {
                LogTextBox.AppendText(message + "
");
                LogTextBox.ScrollToEnd();
            });
        }

        public event PropertyChangedEventHandler PropertyChanged;
        protected void OnPropertyChanged([CallerMemberName] string name = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
        }
    }

    public class ImageItem : INotifyPropertyChanged
    {
        private string _filePath;
        private string _fileName;
        private string _ocrResult;
        private string _status;
        private System.Windows.Media.Imaging.BitmapImage _thumbnail;

        public string FilePath
        {
            get => _filePath;
            set
            {
                _filePath = value;
                OnPropertyChanged();
            }
        }

        public string FileName
        {
            get => _fileName;
            set
            {
                _fileName = value;
                OnPropertyChanged();
            }
        }

        public string OcrResult
        {
            get => _ocrResult;
            set
            {
                _ocrResult = value;
                OnPropertyChanged();
            }
        }

        public string Status
        {
            get => _status;
            set
            {
                _status = value;
                OnPropertyChanged();
            }
        }

        public System.Windows.Media.Imaging.BitmapImage Thumbnail
        {
            get => _thumbnail;
            set
            {
                _thumbnail = value;
                OnPropertyChanged();
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        protected void OnPropertyChanged([CallerMemberName] string name = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
        }
    }
}
2.5 TencentOcrClient.cs
代码语言:javascript
代码运行次数:0
运行
复制
csharpusing Newtonsoft.Json.Linq;
using System;
using System.IO;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using TencentCloud.Common;
using TencentCloud.Common.Profile;
using TencentCloud.Ocr.V20181119;
using TencentCloud.Ocr.V20181119.Models;

namespace ImageOCRRenamer.Services
{
    public class TencentOcrClient
    {
        private readonly OcrClient _client;

        public TencentOcrClient(string secretId, string secretKey)
        {
            try
            {
                var cred = new Credential(secretId, secretKey);
                var httpProfile = new HttpProfile();
                httpProfile.Endpoint = "ocr.tencentcloudapi.com";
                var clientProfile = new ClientProfile();
                clientProfile.HttpProfile = httpProfile;
                _client = new OcrClient(cred, "ap-guangzhou", clientProfile);
            }
            catch (Exception ex)
            {
                throw new Exception("初始化腾讯OCR客户端失败: " + ex.Message);
            }
        }

        public async Task<string> GeneralBasicOCR(string imagePath)
        {
            try
            {
                var req = new GeneralBasicOCRRequest();
                using (var imageStream = new FileStream(imagePath, FileMode.Open, FileAccess.Read))
                {
                    var imageBytes = new byte[imageStream.Length];
                    await imageStream.ReadAsync(imageBytes, 0, imageBytes.Length);
                    req.ImageBase64 = Convert.ToBase64String(imageBytes);
                }

                var resp = await _client.GeneralBasicOCR(req);
                return FormatOCRResult(resp.TextDetections);
            }
            catch (Exception ex)
            {
                throw new Exception("OCR识别失败: " + ex.Message);
            }
        }

        private string FormatOCRResult(JArray detections)
        {
            var result = new StringBuilder();
            foreach (var detection in detections)
            {
                if (detection["DetectedText"] != null)
                {
                    result.AppendLine(detection["DetectedText"].ToString());
                }
            }
            return result.ToString();
        }
    }
}

注意:上述TencentOcrClient类简化了腾讯OCR API的调用过程。实际项目中,建议参考腾讯云官方文档和SDK,处理更多的返回字段和错误情况。

2.6 配置设置

Properties文件夹下创建Settings.settings,添加腾讯云的SecretIdSecretKey

代码语言:javascript
代码运行次数:0
运行
复制
SecretId (string)
SecretKey (string)

并在代码中读取这些设置:

代码语言:javascript
代码运行次数:0
运行
复制
csharpProperties.Settings.Default.TencentSecretId
Properties.Settings.Default.TencentSecretKey

2.7 OCR结果处理与文件重命名

StartRecognition_Click方法中,添加根据OCR结果重命名文件的逻辑。例如,提取识别到的第一个文本作为新文件名:

代码语言:javascript
代码运行次数:0
运行
复制
csharpprivate async void StartRecognition_Click(object sender, RoutedEventArgs e)
{
    if (string.IsNullOrEmpty(Properties.Settings.Default.TencentSecretId) ||
        string.IsNullOrEmpty(Properties.Settings.Default.TencentSecretKey))
    {
        MessageBox.Show("请先配置腾讯云的SecretId和SecretKey!");
        return;
    }

    IsProcessing = true;
    Progress = 0;

    var ocrClient = new TencentOcrClient(Properties.Settings.Default.TencentSecretId, Properties.Settings.Default.TencentSecretKey);
    int total = ImageItems.Count;
    int processed = 0;

    foreach (var item in ImageItems)
    {
        try
        {
            string result = await ocrClient.GeneralBasicOCR(item.FilePath);
            item.OcrResult = result.Length > 100 ? result.Substring(0, 100) + "..." : result;

            // 提取第一个识别结果作为新文件名
            var firstLine = result.Split('
').FirstOrDefault();
            if (!string.IsNullOrEmpty(firstLine))
            {
                string newName = SanitizeFileName(firstLine) + Path.GetExtension(item.FilePath);
                string newPath = Path.Combine(Path.GetDirectoryName(item.FilePath), newName);
                int counter = 1;
                while (File.Exists(newPath))
                {
                    newName = $"{SanitizeFileName(firstLine)}_{counter}{Path.GetExtension(item.FilePath)}";
                    newPath = Path.Combine(Path.GetDirectoryName(item.FilePath), newName);
                    counter++;
                }
                File.Move(item.FilePath, newPath);
                item.FilePath = newPath;
                item.FileName = Path.GetFileName(newPath);
            }
        }
        catch (Exception ex)
        {
            item.Status = "识别失败: " + ex.Message;
            Log("识别失败: " + item.FileName + " - " + ex.Message);
        }
        finally
        {
            processed++;
            Progress = (int)(((double)processed / total) * 100);
        }
    }

    IsProcessing = false;
    Log("所有图片已处理完成!");
}

private string SanitizeFileName(string input)
{
    return new string(input.Where(c => !Path.GetInvalidFileNameChars().Contains(c)).ToArray());
}

注意

  • 文件名合法性:确保提取的文本不包含非法字符,使用SanitizeFileName方法进行过滤。
  • 文件存在检查:在重命名时检查新文件名是否已存在,避免覆盖已有文件。
  • 错误处理:在捕获异常时记录错误信息,避免程序崩溃。

四、项目总结

本项目基于WPF和腾讯OCR技术,实现了一个批量图片文字识别与重命名的桌面应用程序。通过以下步骤,完成了从需求分析到功能实现的全过程:

1. 功能实现

  • 图片加载与展示:用户可以通过界面选择包含图片的文件夹,程序加载并展示图片的缩略图、文件名及识别状态。
  • OCR文字识别:利用腾讯OCR API对每张图片进行文字识别,提取图片中的文本内容。
  • 结果处理与文件重命名:根据识别到的文字内容,自动重命名图片文件,确保文件名的唯一性和可读性。
  • 进度与日志显示:实时显示处理进度和操作日志,提升用户体验。

2. 技术要点

  • WPF界面设计:使用MVVM模式(虽然本示例中未完全实现MVVM,但可以进一步优化),结合数据绑定和命令模式,提高代码的可维护性和可扩展性。
  • 腾讯OCR API集成:通过腾讯云提供的.NET SDK,简化了API调用的过程,同时需要处理认证、请求和响应的细节。
  • 异步编程:利用asyncawait关键字,确保UI界面的响应性,避免因网络请求导致的界面卡顿。
  • 错误处理与健壮性:在文件操作和API调用中加入异常处理,确保程序在遇到错误时能够稳定运行,并提供有用的错误信息。

3. 优化方向

  • 性能优化:对于大量图片的处理,可以考虑引入多线程或并行处理,提高处理速度。
  • 高级OCR功能:利用腾讯OCR提供的高级功能,如表格识别

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
作者已关闭评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、项目背景
  • 二、界面设计
    • 1. 主窗口布局
    • 2. 用户流程
  • 三、详细代码
    • 1. 项目结构
    • 2. 主要代码实现
      • 2.1 安装必要的NuGet包
      • 2.2 配置腾讯OCR API
      • 2.3 MainWindow.xaml
      • 2.4 MainWindow.xaml.cs
      • 2.5 TencentOcrClient.cs
      • 2.6 配置设置
    • 2.7 OCR结果处理与文件重命名
  • 四、项目总结
    • 1. 功能实现
    • 2. 技术要点
    • 3. 优化方向
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档