首页 > 其他分享 >图像简单处理

图像简单处理

时间:2024-04-17 10:33:37浏览次数:24  
标签:处理 图像 Cv2 System new int 简单 var using

需求:对上面多张这样的图像,将成员识别出来,读取本周活跃值。生成一张全部由成员组成的大图

思路:使用OpenCVSharp进行目标区域边框检测,根据大小过滤目标区域。使用Tesseract对指定位置进行文字识别(貌似识别精度不高,有乱码。)

主要代码

using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Security.Cryptography;
using System.Web;
using System.Windows;
using System.Windows.Documents;
using OpenCvSharp;
using OpenCvSharp.Dnn;
using OpenCvSharp.Internal.Vectors;
using Tesseract;

namespace ShanHaiJingToolkit.Common
{
    public class CvHelper
    {
        public void ReadPictureActivityValue(string imagePath, out int itemWidth, out int itemHeight)
        {
            System.IO.DirectoryInfo directoryInfo = new System.IO.DirectoryInfo(imagePath);
            List<Mat> items = new List<Mat>();
            itemWidth = 0;
            itemHeight = 0;
            foreach (var file in directoryInfo.GetFiles())
            {
                // 读取图像  
                using (var src = new Mat(file.FullName, ImreadModes.Color))
                {
                    // 转换为灰度图像,因为边缘检测通常在灰度图像上进行  
                    using (var gray = new Mat())
                    {
                        Cv2.CvtColor(src, gray, ColorConversionCodes.BGR2GRAY);

                        // 应用Canny边缘检测  
                        using (var edges = new Mat())
                        {
                            double lowThreshold = 50.0;
                            double highThreshold = 150.0;
                            Cv2.Canny(gray, edges, lowThreshold, highThreshold);
                            Cv2.FindContours(edges, out var contours1, out var hierarchy1, RetrievalModes.List, ContourApproximationModes.ApproxSimple);
                            // 定义矩形颜色(BGR格式)和线条厚度  
                            Scalar color = new Scalar(0, 255, 0); // 绿色 

                            List<OpenCvSharp.Rect> listRects = new List<OpenCvSharp.Rect>();
                            for (int i = 0; i < contours1.Length; i++)
                            {
                                var points = contours1[i];
                                var rect = Cv2.BoundingRect(points);
                                var widthScale = (float)rect.Width / src.Width;
                                var heightScale = (float)rect.Height / src.Height;
                                //if ((widthScale > 0.827 && widthScale < 0.871) && (rect.Height > 0.060 && rect.Height < 0.073))
                                if ((widthScale > 0.827 && widthScale < 0.871) && (heightScale > 0.060 && heightScale < 0.073))
                                {
                                    bool isAdd = false;
                                    foreach (var item in listRects)
                                    {
                                        if (item.TopLeft.DistanceTo(rect.TopLeft) < 10)
                                        {
                                            isAdd = true;
                                            break;
                                        }
                                    }
                                    if (isAdd) continue;
                                    listRects.Add(rect);
                                    if (itemWidth == 0)
                                    {
                                        itemWidth = rect.Width;
                                        itemHeight = rect.Height;
                                    }
                                    var newRect = new OpenCvSharp.Rect(rect.Left, rect.Top, itemWidth, itemHeight);
                                    // 在图像上绘制矩形  
                                    //Cv2.Rectangle(src, newRect.TopLeft, newRect.BottomRight, color, 4);
                                    var tempMat = src[newRect];
                                    items.Add(tempMat);
                                }
                            }
                        }
                    }
                }
            }
            var tempImagesDirectory = imagePath + "\\temp\\";
            if (!System.IO.Directory.Exists(tempImagesDirectory))
            {
                System.IO.Directory.CreateDirectory(tempImagesDirectory);
            }
            //保存到本地
            for (int i = 0; i < items.Count; i++)
            {
                //using (Mat gray = new Mat())
                //{
                //    Cv2.CvtColor(items[i], gray, ColorConversionCodes.BGR2GRAY);
                //    //二值化
                //    using (Mat target = new Mat())
                //    {
                //        Cv2.Threshold(items[i], target, 150, 200, ThresholdTypes.Binary);
                //        Cv2.ImWrite(tempImagesDirectory + $"{i}.png", target);
                //    }
                //}

                //降噪高斯模糊,边缘检测
                // 定义高斯模糊的核大小和标准差  
                //OpenCvSharp.Size ksize = new OpenCvSharp.Size(5, 5); // 核大小,必须是奇数  
                //double sigmaX = 0; // X方向的标准差,如果为0,则由核函数宽度计算得出  
                //double sigmaY = 0; // Y方向的标准差,如果为0,则由核函数高度计算得出  

                //// 应用高斯模糊
                //using (Mat blurredImage = new Mat())
                //{
                //    Cv2.GaussianBlur(items[i], blurredImage, ksize, sigmaX, sigmaY);
                //    // 定义Canny边缘检测的双阈值  
                //    double threshold1 = 50.0; // 低阈值  
                //    double threshold2 = 150.0; // 高阈值,通常是高于低阈值的2到3倍  

                //    // 边缘检测  
                //    using (Mat edges = new Mat())
                //    {
                //        Cv2.Canny(blurredImage, edges, threshold1, threshold2);
                //        Cv2.ImWrite(tempImagesDirectory + $"{i}.png", edges);
                //    }
                //};
                using (Mat txtMat = items[i][new OpenCvSharp.Rect((int)(0.181 * itemWidth), itemHeight / 2, (int)(0.353 * itemWidth), itemHeight / 2)])
                {
                    Cv2.ImWrite(tempImagesDirectory + $"{i}.png", txtMat);
                }
                //Cv2.ImWrite(tempImagesDirectory + $"{i}.png", items[i]);
            }
            //读取活跃值
            List<Tuple<int, Mat>> targetVals = new List<Tuple<int, Mat>>();
            var modelPath = AppDomain.CurrentDomain.BaseDirectory;
            using (var engine = new TesseractEngine(modelPath, "chi_sim", EngineMode.Default))
            {
                for (int i = 0; i < items.Count; i++)
                {
                    var imageFile = tempImagesDirectory + $"{i}.png";
                    // 打开图片并识别文字  
                    var readTxt = string.Empty;
                    using (var img = Pix.LoadFromFile(imageFile))
                    {
                        using (var page = engine.Process(img))
                        {
                            readTxt = page.GetText();
                        }
                    }
                    System.Text.RegularExpressions.MatchCollection matchCollection = System.Text.RegularExpressions.Regex.Matches(readTxt, "\\d+");
                    if (matchCollection.Count > 0)
                    {
                        int.TryParse(matchCollection[matchCollection.Count - 1].Value, out var val);
                        targetVals.Add(new Tuple<int, Mat>(val, items[i]));
                        if (File.Exists(imageFile))
                        {
                            File.Delete(imageFile);
                        }
                    }
                }
            }
            //if (items.Count != targetVals.Count)
            //{
            //    return false;
            //}
            //识别成功的
            int count = 0;
            foreach (var tuple in targetVals)
            {
                var imageFile = tempImagesDirectory + $"{count++}-{tuple.Item1}.png";
                Cv2.ImWrite(imageFile, tuple.Item2);
            }
            //using (var dst = new Mat())
            //{
            //    Cv2.VConcat(items, dst);
            //    Cv2.ImWrite("E:\\ShanHaiJingPic\\result.jpg", dst);
            //    // 定义新的尺寸  
            //    //OpenCvSharp.Size newSize = new OpenCvSharp.Size(src.Cols / 2, src.Rows / 2); // 缩小到原来的一半
            //    //Cv2.Resize(src, dst, newSize);
            //    //using (var window = new OpenCvSharp.Window("Rectangle Detection"))
            //    //{
            //    //    window.ShowImage(dst);
            //    //    Cv2.WaitKey(0);
            //    //}
            //}
        }
    }
}  

主界面:

<Window x:Class="ShanHaiJingToolkit.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:ShanHaiJingToolkit"
        mc:Ignorable="d"
        Title="统计部落活跃" Height="1020" Width="1050">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="50"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <StackPanel Orientation="Horizontal" VerticalAlignment="Center" Margin="10 0 0 0">
            <TextBlock Text="图片路径:"/>
            <TextBox Text="E:\ShanHaiJingPic\20240415"
                     x:Name="filePath"
                     Width="200"/>
            <TextBlock Text="需要加活跃数:" Margin="10 0 0 0"/>
            <TextBox x:Name="txtAdd" Text="0" Width="100"/>
            <TextBlock Text="生成标题:" Margin="10 0 0 0"/>
            <TextBox x:Name="txtTitle" Text="31305部落活跃奖励 2024-04-08至04-14" Width="250"/>
            <Button Content="统计活跃" Margin="10 0 0 0" Click="Button_Click"/>
            <Button Content="生成大图" Margin="10 0 0 0" Click="Button_Click_1"/>
        </StackPanel>
        <GroupBox Header="数据列表" Grid.Row="1">
            <ScrollViewer>
                <WrapPanel x:Name="dataPanel"/>
            </ScrollViewer>
        </GroupBox>
    </Grid>
</Window>
using ShanHaiJingToolkit.Common;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace ShanHaiJingToolkit
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

        }

        private async void Button_Click(object sender, RoutedEventArgs e)
        {
            dataPanel.Children.Clear();

            var fileDirectory = filePath.Text?.Trim();
            int itemWidth = 0;
            int itemHeight = 0;
            List<string> files = new List<string>();
            await Task.Run(() =>
            {
                try
                {
                    CvHelper cvHelper = new CvHelper();
                    cvHelper.ReadPictureActivityValue(fileDirectory, out itemWidth, out itemHeight);
                }
                catch (Exception ex)
                {
                    Dispatcher.Invoke(() =>
                    {
                        MessageBox.Show("读取出错!");
                    });
                }
                var tempImagesDirectory = fileDirectory + "\\temp\\";
                System.IO.DirectoryInfo directoryInfo = new System.IO.DirectoryInfo(tempImagesDirectory);
                foreach (var file in directoryInfo.GetFiles())
                {
                    files.Add(file.FullName);
                }
            });
            itemWidth /= 3;
            itemHeight /= 3;
            Grid titleGrid = new Grid()
            {
                Width = dataPanel.ActualWidth,
                Height = itemHeight
            };
            TextBlock textBlock = new TextBlock()
            {
                Text = txtTitle.Text,
                FontSize = 30,
                Foreground = Brushes.YellowGreen,
                VerticalAlignment = VerticalAlignment.Center,
                HorizontalAlignment = HorizontalAlignment.Center,
            };
            titleGrid.Children.Add(textBlock);
            dataPanel.Children.Add(titleGrid);
            int.TryParse(txtAdd.Text, out var addVal);
            int sumHuoYue = 0;
            int sumJiangli = 0;

            List<Tuple<int, string>> tuples = new List<Tuple<int, string>>();
            foreach (var file in files)
            {
                var fileName = file.Substring(file.LastIndexOf('\\') + 1).Replace(".png", "");
                int countResult = GetVal(fileName);
                sumHuoYue += countResult;
                countResult += addVal;
                var jiangliCount = GetFinalVal(countResult);
                sumJiangli += jiangliCount;
                tuples.Add(new Tuple<int, string>(jiangliCount, file));
            }
            tuples = tuples.OrderByDescending(x => x.Item1).ToList();
            foreach (var item in tuples)
            {
                Grid grid = new Grid()
                {
                    Width = itemWidth,
                    Height = itemHeight,
                };
                grid.Children.Add(new Image()
                {
                    Source = new BitmapImage(new Uri(item.Item2, UriKind.Absolute)),
                    Width = itemWidth,
                    Height = itemHeight,
                });
                grid.Children.Add(new TextBlock()
                {
                    FontSize = 18,
                    Foreground = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#FF087559")),
                    FontWeight = FontWeights.Bold,
                    Text = $"奖励:{item.Item1}芯",
                    HorizontalAlignment = HorizontalAlignment.Right,
                    VerticalAlignment = VerticalAlignment.Center,
                    Margin = new Thickness(0, 0, 10, 0),
                });
                dataPanel.Children.Add(grid);
            }
            Grid sumGrid = new Grid()
            {
                Width = itemWidth,
                Height = itemHeight,
            };
            var sumTextBlock = new TextBlock()
            {
                FontSize = 20,
                Foreground = Brushes.Red,
                Text = $"总活跃:{sumHuoYue},总奖励芯数:{sumJiangli}",
                VerticalAlignment = VerticalAlignment.Center,
            };
            sumGrid.Children.Add(sumTextBlock);
            dataPanel.Children.Add(sumGrid);
            //底部
            Grid bottomGrid = new Grid()
            {
                Width = dataPanel.ActualWidth,
                Height = itemHeight
            };
            Rectangle rectangle = new Rectangle()
            {
                Width = dataPanel.ActualWidth,
                Height = 2,
                Fill = Brushes.Black
            };
            bottomGrid.Children.Add(rectangle);
            dataPanel.Children.Add(bottomGrid);
        }

        //VLOOKUP(I2,{0,0;280,3;300,4;320,6;340,8;360,9;380,11},2,1)
        int GetFinalVal(int val)
        {
            if (val < 280) return 0;
            if (val <= 300 && val >= 280) return 3;
            if (val <= 320 && val > 300) return 4;
            if (val <= 340 && val > 320) return 6;
            if (val <= 360 && val > 340) return 8;
            if (val <= 380 && val > 360) return 9;
            if (val > 380) return 11;
            return 0;
        }

        int GetVal(string val)
        {
            int result = 0;
            if (!string.IsNullOrEmpty(val))
            {
                var splits = val.Split('-');
                int.TryParse(splits[1], out result);
            }
            return result;
        }

        public void SaveVisualToPng(Visual visual, string filePath, int dpiX = 96, int dpiY = 96)
        {
            // 获取控件的边界大小  
            Rect bounds = VisualTreeHelper.GetDescendantBounds(visual);

            // 创建 RenderTargetBitmap,其大小与控件大小一致,并设置DPI  
            RenderTargetBitmap renderTargetBitmap = new RenderTargetBitmap(
                (int)(bounds.Width * dpiX / 96),
                (int)(bounds.Height * dpiY / 96),
                dpiX,
                dpiY,
                PixelFormats.Pbgra32);

            // 将控件渲染到 RenderTargetBitmap 上  
            renderTargetBitmap.Render(visual);

            // 将 RenderTargetBitmap 编码为 PNG 图片  
            PngBitmapEncoder pngEncoder = new PngBitmapEncoder();
            pngEncoder.Frames.Add(BitmapFrame.Create(renderTargetBitmap));

            // 保存图片到文件  
            using (Stream stream = File.Create(filePath))
            {
                pngEncoder.Save(stream);
            }
        }

        private void Button_Click_1(object sender, RoutedEventArgs e)
        {
            var fileDirectory = filePath.Text?.Trim();
            var fileName = fileDirectory + $"\\{txtTitle.Text}.png";
            SaveVisualToPng(dataPanel, fileName);
            MessageBox.Show("大图生成成功!" + fileName);
            // 使用默认的文件浏览器打开文件夹  
            Process.Start("explorer.exe", fileDirectory);
        }
    }
}

 

标签:处理,图像,Cv2,System,new,int,简单,var,using
From: https://www.cnblogs.com/xunyou/p/18140008

相关文章

  • A7-100T的图像处理开发板
    深圳市飞录科技有限公司一:概述   开发板主控采用XilinxArtix-7系列FPGA,型号为XC7A100T-2FGG676C,具有100KLUTs,240个DSP,芯片集成了LVDS、DDR3,6.6GSerdes等控制器。XilinxArtix-7作为中规模FPGA的典范,选用28nm工艺,性能与解决方案非常成熟,在通信及图像市场的应用非常广......
  • Mysql低版本中处理row_number()函数的适配问题
    在最近的项目中遇到了mysql8.0版本中row_number()函数在迁移数据库低版本mysql5.0版本无法使用的问题。具体sql如下:1SELECTDATE(a.CRETIFICATE_DATE)ASNAME,COUNT(*)ASCOUNTFROM2(SELECTCERTIFICATE_DATE,ENABLED,CERTIFICATION_STATE,ROW_NUMBER()over(PARTIT......
  • ETL工具-nifi干货系列 第十三讲 nifi处理器QueryDatabaseTable查询表数据实战教程
    1、处理器QueryDatabaseTable,该组件生成一个SQL查询,或者使用用户提供的语句,并执行它以获取所有在指定的最大值列中值大于先前所见最大值的行。查询结果将被转换为Avro格式,如下图所示: 本示例通过QueryDatabaseTable处理器连接数据库查询表数据,然后连接到LogMessage打印日志......
  • springboot简单正确的使用构造函数注入
    一个一个写构造函数太麻烦了,而且代码会显得非常多,这里我们可以采用lombok快捷注入但是我们并不是所有的成员变量都需要进行注入,所以使用@RequiredArgsConstrucotr需要构造函数的部分添加上final关键字"Alwaysuseconstructorbaseddependencyinjectioninyourbeans.Alwa......
  • 30.swagger springboot中简单整理
    类似postman接口在线测试API接口哈哈我也不太懂接口还没前后端整合过呢也就是注释你的各种接口吧可有可无先说依赖问题这个是swagger2的依赖当然出现问题了已经更新到了swagger3了参考:https://cloud.tencent.com/developer/article/1936862https://mvnrepos......
  • 【Azure Developer】.Net 简单示例 "文字动图显示" Typing to SVG
    问题描述看见一个有趣的页面,可以把输入的文字信息,直接输出SVG图片,还可以实现动图模式。示例URL: https://readme-typing-svg.demolab.com/?font=Fira+Code&pause=1000&color=F7F7F7&background=233911F6&center=true&vCenter=true&random=false&width=435&lines=%E6%8A%8A%E5%......
  • dbt-checkpoint 源码结构简单说明
    前边说过dbt-checkpoint是基于dbt的元数据解析,然后集合规则进行check,属于一个pre-commit插件,以下简单说明下内部实现配置核心是.pre-commit-hooks.yaml文件,一个标准的pre-commit定义内容核心是id,name,entry,language,entry实际上就是一个pythonentry_points的console_......
  • 自定义pre-commit 开发格式简单说明
    内容来自官方文档,主要是简单说明下,方便学习约定git项目需要包含.pre-commit-hooks.yaml文件,里边内容格式如下-id:trailing-whitespacename:TrimTrailingWhitespacedescription:Thishooktrimstrailingwhitespace.entry:trailing-w......
  • 简单用VBS调用企业微信机器人发定时消息的方法
    <p>去年在企业微信群当中突然看到多了一个叫多群机器人的东西:</p>企业微信群机器人以为是升级了什么黑科技,看了下说明,原来目前功能是一个接收自定义消息的Webhook接口,可以通过调用接口把自定义消息推送到机器人所在的群当中。虽然看上去很简单,想想还......
  • 自动以管理员身份运行批处理bat文件(vbs与bat两种方法)
    <p>但是,批处理脚本不会默认已管理员身份运行,一般情况下,我会将脚本命名为"XXXXXX(请右键点击,用管理员身份运行!).bat",但总有些用户会忽略这条提示,直接运行,此时由于权限不足,导致脚本运行失败。</p>我们可以使用一种变通的方法,让bat启动时,首先调用vbs脚本,......