init
This commit is contained in:
parent
b5a5ffeaa3
commit
2e2ab7edd1
|
|
@ -0,0 +1,107 @@
|
|||
name: 部署开发环境
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- develop
|
||||
|
||||
env:
|
||||
IMAGE_NAME: ${{ gitea.repository_owner }}/marking.ocr.service
|
||||
PROJECT_NAME: Marking.OCR.Service
|
||||
PUBLISH_PATH: marking.ocr.service
|
||||
PUBLISH_HOST: 192.168.2.9
|
||||
PUBLISH_PORT: 22
|
||||
PUBLISH_REPLICAS: 1 #启动副本数量
|
||||
ASPNETCORE_ENVIRONMENT: Development
|
||||
|
||||
jobs:
|
||||
job1:
|
||||
name: 编译发布
|
||||
runs-on: linux-amd
|
||||
|
||||
steps:
|
||||
- name: 下载源码
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: 使用缓存
|
||||
uses: actions/cache@master
|
||||
with:
|
||||
cache_type: nuget
|
||||
mount: |
|
||||
nuget
|
||||
|
||||
- name: 编译后端项目
|
||||
uses: actions/aspnet@8.0
|
||||
with:
|
||||
project_name: ${{ env.PROJECT_NAME }}
|
||||
|
||||
- name: 打包上传镜像
|
||||
uses: actions/docker@master
|
||||
with:
|
||||
registry: ${{ secrets.DOCKER_REGISTRY }}
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
image: ${{ env.IMAGE_NAME }}
|
||||
context: publish
|
||||
tags: latest,${{ gitea.ref_name }}
|
||||
|
||||
- name: 生成环境变量文件
|
||||
env:
|
||||
env_file: |
|
||||
REGISTRY=${{ secrets.DOCKER_REGISTRY }}
|
||||
OWNER=${{ gitea.repository_owner }}
|
||||
TAG=${{ gitea.ref_name }}
|
||||
ASPNETCORE_ENVIRONMENT=${{ env.ASPNETCORE_ENVIRONMENT }}
|
||||
REPLICAS=${{ env.PUBLISH_REPLICAS }}
|
||||
run: |
|
||||
echo "$env_file">.env
|
||||
|
||||
- name: 复制发布脚本
|
||||
uses: docker://appleboy/drone-scp
|
||||
with:
|
||||
host: ${{ env.PUBLISH_HOST }}
|
||||
port: ${{ env.PUBLISH_PORT }}
|
||||
username: ${{ secrets.PUBLISH_USER_NAME }}
|
||||
password: ${{ secrets.PUBLISH_PASSWORD }}
|
||||
target: ${{ env.PUBLISH_PATH }}
|
||||
source: docker-swarm.yaml,.env
|
||||
|
||||
- name: 部署到服务器
|
||||
uses: docker://appleboy/drone-ssh
|
||||
with:
|
||||
host: ${{ env.PUBLISH_HOST }}
|
||||
port: ${{ env.PUBLISH_PORT }}
|
||||
username: ${{ secrets.PUBLISH_USER_NAME }}
|
||||
password: ${{ secrets.PUBLISH_PASSWORD }}
|
||||
script: |
|
||||
if docker service ls | grep -q marking-admin-api; then
|
||||
docker service rm marking-admin-api
|
||||
fi
|
||||
|
||||
cd ${{ env.PUBLISH_PATH }}
|
||||
|
||||
[ -f .env ] && export $(sed '/^#/d' .env)
|
||||
|
||||
docker stack deploy -c docker-swarm.yaml --with-registry-auth mk
|
||||
|
||||
- name: 发送构建通知
|
||||
if: ${{ always() }}
|
||||
uses: actions/webhook@master
|
||||
with:
|
||||
urls: https://oapi.dingtalk.com/robot/send?access_token=6ddafcada8f44f4bad4a7314c4d9bd19a895ded0a1ba1afdaff5dd01a5af6781
|
||||
content_type: application/json
|
||||
template: |
|
||||
{
|
||||
"msgtype": "markdown",
|
||||
"markdown": {
|
||||
"title":"项目部署通知",
|
||||
"text": "${{ job.status == 'success' && '✅' || '❌' }}**${{ gitea.repository }}**\n
|
||||
>**构建结果**: ${{ job.status }}
|
||||
>**构建详情**: [点击查看](${{ gitea.server_url }}/${{ gitea.repository }}/actions/runs/${{ gitea.run_number }})
|
||||
>**代码分支**: ${{ gitea.ref_name }}
|
||||
>**提交标识**: ${{ gitea.sha }}
|
||||
>**提交发起**: ${{ gitea.actor }}
|
||||
>**提交信息**: ${{ gitea.event.head_commit.message }}\n
|
||||
"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,124 @@
|
|||
name: 部署生产环境
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
|
||||
env:
|
||||
IMAGE_NAME: ${{ gitea.repository_owner }}/marking.admin.api
|
||||
PROJECT_NAME: src/Marking.Admin.Entry
|
||||
PUBLISH_PATH: marking.admin.api
|
||||
PUBLISH_HOST: 10.255.255.146,10.255.255.74
|
||||
PUBLISH_PORT: 10022
|
||||
PUBLISH_REPLICAS: 2 #启动副本数量
|
||||
ASPNETCORE_ENVIRONMENT: Production
|
||||
|
||||
jobs:
|
||||
release:
|
||||
name: 发布版本
|
||||
runs-on: linux
|
||||
|
||||
outputs:
|
||||
version: ${{ steps.publish_version.outputs.version }}
|
||||
|
||||
steps:
|
||||
- name: 下载源码
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: 发布版本
|
||||
id: publish_version
|
||||
uses: actions/auto-release@master
|
||||
|
||||
job1:
|
||||
name: 编译发布
|
||||
runs-on: linux-amd
|
||||
needs: release
|
||||
|
||||
steps:
|
||||
- name: 下载源码
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: 使用缓存
|
||||
uses: actions/cache@master
|
||||
with:
|
||||
cache_type: nuget
|
||||
mount: |
|
||||
nuget
|
||||
|
||||
- name: 编译后端项目
|
||||
uses: actions/aspnet@6.0
|
||||
with:
|
||||
project_name: ${{ env.PROJECT_NAME }}
|
||||
|
||||
- name: 打包上传镜像
|
||||
uses: actions/docker@master
|
||||
with:
|
||||
registry: ${{ secrets.DOCKER_REGISTRY }}
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
image: ${{ env.IMAGE_NAME }}
|
||||
context: publish
|
||||
tags: latest,${{ gitea.ref_name }},${{ needs.release.outputs.version }}
|
||||
|
||||
- name: 生成环境变量文件
|
||||
env:
|
||||
env_file: |
|
||||
REGISTRY=${{ secrets.DOCKER_REGISTRY }}
|
||||
OWNER=${{ gitea.repository_owner }}
|
||||
TAG=${{ needs.release.outputs.version }}
|
||||
ASPNETCORE_ENVIRONMENT=${{ env.ASPNETCORE_ENVIRONMENT }}
|
||||
REPLICAS=${{ env.PUBLISH_REPLICAS }}
|
||||
run: |
|
||||
echo "$env_file">.env
|
||||
|
||||
- name: 复制发布脚本
|
||||
uses: docker://appleboy/drone-scp
|
||||
with:
|
||||
host: ${{ env.PUBLISH_HOST }}
|
||||
port: ${{ env.PUBLISH_PORT }}
|
||||
username: ${{ secrets.PUBLISH_USER_NAME }}
|
||||
password: ${{ secrets.PUBLISH_PASSWORD }}
|
||||
target: ${{ env.PUBLISH_PATH }}
|
||||
source: docker-swarm.yaml,.env
|
||||
|
||||
- name: 部署到服务器
|
||||
uses: docker://appleboy/drone-ssh
|
||||
with:
|
||||
host: ${{ env.PUBLISH_HOST }}
|
||||
port: ${{ env.PUBLISH_PORT }}
|
||||
username: ${{ secrets.PUBLISH_USER_NAME }}
|
||||
password: ${{ secrets.PUBLISH_PASSWORD }}
|
||||
script: |
|
||||
if docker service ls | grep -q marking-admin-api; then
|
||||
docker service rm marking-admin-api
|
||||
fi
|
||||
|
||||
cd ${{ env.PUBLISH_PATH }}
|
||||
|
||||
[ -f .env ] && export $(sed '/^#/d' .env)
|
||||
|
||||
docker stack deploy -c docker-swarm.yaml --with-registry-auth mk
|
||||
|
||||
- name: 发送构建通知
|
||||
if: ${{ always() }}
|
||||
uses: actions/webhook@master
|
||||
with:
|
||||
urls: https://oapi.dingtalk.com/robot/send?access_token=6ddafcada8f44f4bad4a7314c4d9bd19a895ded0a1ba1afdaff5dd01a5af6781
|
||||
content_type: application/json
|
||||
template: |
|
||||
{
|
||||
"msgtype": "markdown",
|
||||
"markdown": {
|
||||
"title":"项目部署通知",
|
||||
"text": "${{ job.status == 'success' && '✅' || '❌' }}**${{ gitea.repository }}**\n
|
||||
>**构建结果**: ${{ job.status }}
|
||||
>**构建详情**: [点击查看](${{ gitea.server_url }}/${{ gitea.repository }}/actions/runs/${{ gitea.run_number }})
|
||||
>**代码分支**: ${{ gitea.ref_name }}
|
||||
>**发布版本**: ${{ needs.release.outputs.version }}
|
||||
>**提交标识**: ${{ gitea.sha }}
|
||||
>**提交发起**: ${{ gitea.actor }}
|
||||
>**提交信息**: ${{ gitea.event.head_commit.message }}\n
|
||||
"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,107 @@
|
|||
name: 部署测试环境
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- staging
|
||||
|
||||
env:
|
||||
IMAGE_NAME: ${{ gitea.repository_owner }}/marking.admin.api
|
||||
PROJECT_NAME: src/Marking.Admin.Entry
|
||||
PUBLISH_PATH: marking.admin.api
|
||||
PUBLISH_HOST: 10.255.255.3
|
||||
PUBLISH_PORT: 22
|
||||
PUBLISH_REPLICAS: 3 #启动副本数量
|
||||
ASPNETCORE_ENVIRONMENT: Staging
|
||||
|
||||
jobs:
|
||||
job1:
|
||||
name: 编译发布
|
||||
runs-on: linux-amd
|
||||
|
||||
steps:
|
||||
- name: 下载源码
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: 使用缓存
|
||||
uses: actions/cache@master
|
||||
with:
|
||||
cache_type: nuget
|
||||
mount: |
|
||||
nuget
|
||||
|
||||
- name: 编译后端项目
|
||||
uses: actions/aspnet@6.0
|
||||
with:
|
||||
project_name: ${{ env.PROJECT_NAME }}
|
||||
|
||||
- name: 打包上传镜像
|
||||
uses: actions/docker@master
|
||||
with:
|
||||
registry: ${{ secrets.DOCKER_REGISTRY }}
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
image: ${{ env.IMAGE_NAME }}
|
||||
context: publish
|
||||
tags: latest,${{ gitea.ref_name }}
|
||||
|
||||
- name: 生成环境变量文件
|
||||
env:
|
||||
env_file: |
|
||||
REGISTRY=${{ secrets.DOCKER_REGISTRY }}
|
||||
OWNER=${{ gitea.repository_owner }}
|
||||
TAG=${{ gitea.ref_name }}
|
||||
ASPNETCORE_ENVIRONMENT=${{ env.ASPNETCORE_ENVIRONMENT }}
|
||||
REPLICAS=${{ env.PUBLISH_REPLICAS }}
|
||||
run: |
|
||||
echo "$env_file">.env
|
||||
|
||||
- name: 复制发布脚本
|
||||
uses: docker://appleboy/drone-scp
|
||||
with:
|
||||
host: ${{ env.PUBLISH_HOST }}
|
||||
port: ${{ env.PUBLISH_PORT }}
|
||||
username: ${{ secrets.PUBLISH_USER_NAME }}
|
||||
password: ${{ secrets.PUBLISH_PASSWORD }}
|
||||
target: ${{ env.PUBLISH_PATH }}
|
||||
source: docker-swarm.yaml,.env
|
||||
|
||||
- name: 部署到服务器
|
||||
uses: docker://appleboy/drone-ssh
|
||||
with:
|
||||
host: ${{ env.PUBLISH_HOST }}
|
||||
port: ${{ env.PUBLISH_PORT }}
|
||||
username: ${{ secrets.PUBLISH_USER_NAME }}
|
||||
password: ${{ secrets.PUBLISH_PASSWORD }}
|
||||
script: |
|
||||
if docker service ls | grep -q marking-admin-api; then
|
||||
docker service rm marking-admin-api
|
||||
fi
|
||||
|
||||
cd ${{ env.PUBLISH_PATH }}
|
||||
|
||||
[ -f .env ] && export $(sed '/^#/d' .env)
|
||||
|
||||
docker stack deploy -c docker-swarm.yaml --with-registry-auth mk
|
||||
|
||||
- name: 发送构建通知
|
||||
if: ${{ always() }}
|
||||
uses: actions/webhook@master
|
||||
with:
|
||||
urls: https://oapi.dingtalk.com/robot/send?access_token=6ddafcada8f44f4bad4a7314c4d9bd19a895ded0a1ba1afdaff5dd01a5af6781
|
||||
content_type: application/json
|
||||
template: |
|
||||
{
|
||||
"msgtype": "markdown",
|
||||
"markdown": {
|
||||
"title":"项目部署通知",
|
||||
"text": "${{ job.status == 'success' && '✅' || '❌' }}**${{ gitea.repository }}**\n
|
||||
>**构建结果**: ${{ job.status }}
|
||||
>**构建详情**: [点击查看](${{ gitea.server_url }}/${{ gitea.repository }}/actions/runs/${{ gitea.run_number }})
|
||||
>**代码分支**: ${{ gitea.ref_name }}
|
||||
>**提交标识**: ${{ gitea.sha }}
|
||||
>**提交发起**: ${{ gitea.actor }}
|
||||
>**提交信息**: ${{ gitea.event.head_commit.message }}\n
|
||||
"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,107 @@
|
|||
name: 部署生产环境
|
||||
|
||||
on:
|
||||
release:
|
||||
types:
|
||||
- published
|
||||
|
||||
env:
|
||||
IMAGE_NAME: ${{ gitea.repository_owner }}/marking.admin.api
|
||||
PROJECT_NAME: src/Marking.Admin.Entry
|
||||
PUBLISH_PATH: marking.admin.api
|
||||
PUBLISH_HOST: 10.255.255.146,10.255.255.74
|
||||
PUBLISH_PORT: 10022
|
||||
PUBLISH_REPLICAS: 3 #启动副本数量
|
||||
ASPNETCORE_ENVIRONMENT: Production
|
||||
|
||||
jobs:
|
||||
job1:
|
||||
name: 编译发布
|
||||
runs-on: linux-amd
|
||||
|
||||
steps:
|
||||
- name: 下载源码
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: 使用缓存
|
||||
uses: actions/cache@master
|
||||
with:
|
||||
cache_type: nuget
|
||||
mount: |
|
||||
nuget
|
||||
|
||||
- name: 编译后端项目
|
||||
uses: actions/aspnet@6.0
|
||||
with:
|
||||
project_name: ${{ env.PROJECT_NAME }}
|
||||
|
||||
- name: 打包上传镜像
|
||||
uses: actions/docker@master
|
||||
with:
|
||||
registry: ${{ secrets.DOCKER_REGISTRY }}
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
image: ${{ env.IMAGE_NAME }}
|
||||
context: publish
|
||||
tags: latest,${{ gitea.ref_name }}
|
||||
|
||||
- name: 生成环境变量文件
|
||||
env:
|
||||
env_file: |
|
||||
REGISTRY=${{ secrets.DOCKER_REGISTRY }}
|
||||
OWNER=${{ gitea.repository_owner }}
|
||||
TAG=${{ gitea.ref_name }}
|
||||
ASPNETCORE_ENVIRONMENT=${{ env.ASPNETCORE_ENVIRONMENT }}
|
||||
REPLICAS=${{ env.PUBLISH_REPLICAS }}
|
||||
run: |
|
||||
echo "$env_file">.env
|
||||
|
||||
- name: 复制发布脚本
|
||||
uses: docker://appleboy/drone-scp
|
||||
with:
|
||||
host: ${{ env.PUBLISH_HOST }}
|
||||
port: ${{ env.PUBLISH_PORT }}
|
||||
username: ${{ secrets.PUBLISH_USER_NAME }}
|
||||
password: ${{ secrets.PUBLISH_PASSWORD }}
|
||||
target: ${{ env.PUBLISH_PATH }}
|
||||
source: docker-swarm.yaml,.env
|
||||
|
||||
- name: 部署到服务器
|
||||
uses: docker://appleboy/drone-ssh
|
||||
with:
|
||||
host: ${{ env.PUBLISH_HOST }}
|
||||
port: ${{ env.PUBLISH_PORT }}
|
||||
username: ${{ secrets.PUBLISH_USER_NAME }}
|
||||
password: ${{ secrets.PUBLISH_PASSWORD }}
|
||||
script: |
|
||||
if docker service ls | grep -q marking-admin-api; then
|
||||
docker service rm marking-admin-api
|
||||
fi
|
||||
|
||||
cd ${{ env.PUBLISH_PATH }}
|
||||
|
||||
[ -f .env ] && export $(sed '/^#/d' .env)
|
||||
|
||||
docker stack deploy -c docker-swarm.yaml --with-registry-auth mk
|
||||
|
||||
- name: 发送构建通知
|
||||
if: ${{ always() }}
|
||||
uses: actions/webhook@master
|
||||
with:
|
||||
urls: https://oapi.dingtalk.com/robot/send?access_token=6ddafcada8f44f4bad4a7314c4d9bd19a895ded0a1ba1afdaff5dd01a5af6781
|
||||
content_type: application/json
|
||||
template: |
|
||||
{
|
||||
"msgtype": "markdown",
|
||||
"markdown": {
|
||||
"title":"项目部署通知",
|
||||
"text": "${{ job.status == 'success' && '✅' || '❌' }}**${{ gitea.repository }}**\n
|
||||
>**构建结果**: ${{ job.status }}
|
||||
>**构建详情**: [点击查看](${{ gitea.server_url }}/${{ gitea.repository }}/actions/runs/${{ gitea.run_number }})
|
||||
>**代码分支**: ${{ gitea.ref_name }}
|
||||
>**提交标识**: ${{ gitea.sha }}
|
||||
>**提交发起**: ${{ gitea.actor }}
|
||||
>**提交信息**: ${{ gitea.event.release.target_commitish }}\n
|
||||
"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
using Marking.OCR.Service.Helper;
|
||||
using System.Timers;
|
||||
|
||||
namespace Marking.OCR.Service.BackgroundServices
|
||||
{
|
||||
|
||||
public class CheckAndDeleteFilesService : BackgroundService
|
||||
{
|
||||
private static System.Timers.Timer timer;
|
||||
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
||||
{
|
||||
await Console.Out.WriteLineAsync("定时删除jpg文件已开启!" + App.HostEnvironment.EnvironmentName);
|
||||
|
||||
timer = new System.Timers.Timer(24 * 60 * 60 * 1000); // 设置定时器为24小时
|
||||
timer.Elapsed += new ElapsedEventHandler(CheckAndDeleteFiles);
|
||||
timer.Start();
|
||||
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
|
||||
private static void CheckAndDeleteFiles(object source, ElapsedEventArgs e)
|
||||
{
|
||||
Console.WriteLine("开始执行删除文件,当前时间:" + DateTime.Now);
|
||||
if (!Directory.Exists(ImageHelper.FilePath))
|
||||
{
|
||||
Directory.CreateDirectory(ImageHelper.FilePath);
|
||||
}
|
||||
|
||||
string folderPath = ImageHelper.FilePath;
|
||||
string[] files = Directory.GetFiles(folderPath, "*.jpg");
|
||||
Console.WriteLine("图片总数:" + files.Length);
|
||||
foreach (string file in files)
|
||||
{
|
||||
DateTime creationTime = File.GetCreationTime(file);
|
||||
TimeSpan timeSpan = DateTime.Now - creationTime;
|
||||
if (timeSpan.TotalDays > 1) // 超过一天直接删除,避免占用磁盘空间
|
||||
{
|
||||
File.Delete(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
using Marking.OCR.Service.DTO;
|
||||
using Marking.OCR.Service.Helper;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using OpenCvSharp;
|
||||
|
||||
namespace Marking.OCR.Service.Controllers
|
||||
{
|
||||
[ApiController]
|
||||
[Route("draw")]
|
||||
public class DrawTemplateController : ControllerBase
|
||||
{
|
||||
|
||||
|
||||
private readonly ILogger<DrawTemplateController> _logger;
|
||||
private readonly ImageHelper _imageHelper;
|
||||
|
||||
public DrawTemplateController(ILogger<DrawTemplateController> logger,
|
||||
ImageHelper imageHelper)
|
||||
{
|
||||
_logger = logger;
|
||||
this._imageHelper = imageHelper;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取模板截图定位点坐标信息
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpGet("position")]
|
||||
public async Task<LocationPointViewDto> GetPositionAsync([FromQuery] LocationPointQueryDto position)
|
||||
{
|
||||
using var src = await _imageHelper.DownloadImageAsync(position.ImageUrl);
|
||||
if (src == null)
|
||||
{
|
||||
throw Oops.Oh("图片加载失败!");
|
||||
}
|
||||
// 调整图片大小
|
||||
Cv2.Resize(src, src, new Size(position.ImageWidth, position.ImageHeight));
|
||||
//_imageHelper.Show(src);
|
||||
|
||||
// 裁剪图片
|
||||
using var img_roi = new Mat(src, new Rect(position.X, position.Y, position.Width, position.Height));
|
||||
//_imageHelper.Show(img_roi);
|
||||
|
||||
// 转换灰度图片
|
||||
Cv2.CvtColor(img_roi, img_roi, ColorConversionCodes.BGR2GRAY);
|
||||
//_imageHelper.Show(img_roi);
|
||||
|
||||
using var imgHandle = _imageHelper.ImagePreprocessing(img_roi);
|
||||
|
||||
var locationPoints = _imageHelper.FindLocationPoint(imgHandle, false);
|
||||
if (!locationPoints.Any())
|
||||
{
|
||||
throw Oops.Oh("框选范围未找到定位点,请重新框选!");
|
||||
}
|
||||
if (locationPoints.Count() > 1)
|
||||
{
|
||||
throw Oops.Oh("框选范围识别到多个定位点,请重新框选!");
|
||||
}
|
||||
|
||||
var locationPoint = locationPoints.FirstOrDefault();
|
||||
return new LocationPointViewDto
|
||||
{
|
||||
X = locationPoint.X + position.X,
|
||||
Y = locationPoint.Y + position.Y,
|
||||
Width = locationPoint.Width,
|
||||
Height = locationPoint.Height
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Marking.OCR.Service.Controllers
|
||||
{
|
||||
[ApiController]
|
||||
[Route("[controller]")]
|
||||
public class WeatherForecastController : ControllerBase
|
||||
{
|
||||
private static readonly string[] Summaries = new[]
|
||||
{
|
||||
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
|
||||
};
|
||||
|
||||
private readonly ILogger<WeatherForecastController> _logger;
|
||||
|
||||
public WeatherForecastController(ILogger<WeatherForecastController> logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
[HttpGet(Name = "GetWeatherForecast")]
|
||||
public IEnumerable<WeatherForecast> Get()
|
||||
{
|
||||
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
|
||||
{
|
||||
Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
|
||||
TemperatureC = Random.Shared.Next(-20, 55),
|
||||
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
|
||||
})
|
||||
.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
public class WeatherForecast
|
||||
{
|
||||
public DateOnly Date { get; set; }
|
||||
public int TemperatureC { get; set; }
|
||||
public string Summary { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
namespace Marking.OCR.Service.DTO
|
||||
{
|
||||
public class LocationPointQueryDto
|
||||
{
|
||||
public int X { get; set; }
|
||||
public int Y { get; set; }
|
||||
public int Width { get; set; }
|
||||
|
||||
public int Height { get; set; }
|
||||
|
||||
public string ImageUrl { get; set; }
|
||||
|
||||
public int ImageWidth { get; set; }
|
||||
|
||||
public int ImageHeight { get; set; }
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
namespace Marking.OCR.Service.DTO
|
||||
{
|
||||
public class LocationPointViewDto
|
||||
{
|
||||
|
||||
public int X { get; set; }
|
||||
public int Y { get; set; }
|
||||
public int Width { get; set; }
|
||||
|
||||
public int Height { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
#See https://aka.ms/customizecontainer to learn how to customize your debug container and how Visual Studio uses this Dockerfile to build your images for faster debugging.
|
||||
|
||||
FROM dotnet/aspnet:8.0
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
EXPOSE 80
|
||||
|
||||
COPY . .
|
||||
|
||||
ENV TZ=Asia/Shanghai
|
||||
|
||||
ENTRYPOINT ["dotnet", "Marking.OCR.Service.dll"]
|
||||
|
|
@ -0,0 +1,154 @@
|
|||
using OpenCvSharp;
|
||||
using OpenCvSharp.Internal.Vectors;
|
||||
using Qwit;
|
||||
using static System.Runtime.InteropServices.JavaScript.JSType;
|
||||
|
||||
namespace Marking.OCR.Service.Helper
|
||||
{
|
||||
public class ImageHelper : Qwit.IScopedDependency
|
||||
{
|
||||
private readonly IHttpClientFactory _httpClientFactory;
|
||||
/// <summary>
|
||||
/// 图片保存文件的文件夹地址
|
||||
/// </summary>
|
||||
public static string FilePath => Path.Combine(Directory.GetCurrentDirectory(), "images");
|
||||
|
||||
public ImageHelper(IHttpClientFactory httpClientFactory)
|
||||
{
|
||||
this._httpClientFactory = httpClientFactory;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 下载图片,缓存本地一天
|
||||
/// </summary>
|
||||
/// <param name="url"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<Mat?> DownloadImageAsync(string url)
|
||||
{
|
||||
//判断文件夹是否存在
|
||||
if (!Directory.Exists(FilePath))
|
||||
{
|
||||
Directory.CreateDirectory(FilePath);
|
||||
}
|
||||
//文件名
|
||||
var filename = $@"{url.GetMd5String()}.jpg";
|
||||
//保存地址+文件名
|
||||
var savePath = Path.Combine(FilePath, filename);
|
||||
|
||||
if (File.Exists(savePath))
|
||||
{
|
||||
// 文件已存在
|
||||
return Cv2.ImRead(savePath);
|
||||
}
|
||||
|
||||
// 文件不存在,需下载
|
||||
var finalUrl = (url.StartsWith("http:") || url.StartsWith("https:")) ? url : $@"http:{url}";
|
||||
|
||||
// 下载图片
|
||||
using var httpclient = _httpClientFactory.CreateClient();
|
||||
var response = await httpclient.GetAsync(finalUrl);
|
||||
if (response == null || !response.IsSuccessStatusCode)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var imageBytes = await response.Content.ReadAsByteArrayAsync();
|
||||
|
||||
// 将字节数组保存为文件
|
||||
await System.IO.File.WriteAllBytesAsync(savePath, imageBytes);
|
||||
|
||||
// 文件已存在
|
||||
return Cv2.ImRead(savePath);
|
||||
}
|
||||
|
||||
|
||||
public void Show(Mat mat, string title = "")
|
||||
{
|
||||
#if !DEBUG
|
||||
return;
|
||||
#endif
|
||||
|
||||
Cv2.ImShow(string.IsNullOrWhiteSpace(title) ? DateTime.UtcNow.ToString() : title, mat);
|
||||
Cv2.WaitKey(0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 图像预处理
|
||||
/// </summary>
|
||||
public Mat ImagePreprocessing(Mat mat, double threshValue = 210)
|
||||
{
|
||||
// 中值滤波
|
||||
Cv2.MedianBlur(mat, mat, 5);
|
||||
|
||||
//Show(mat, "MedianBlur");
|
||||
// 高斯滤波
|
||||
Cv2.GaussianBlur(mat, mat, new Size(3, 3), 0);
|
||||
//Show(mat, "GaussianBlur");
|
||||
|
||||
// 二值化
|
||||
Cv2.Threshold(mat, mat, threshValue, 255, ThresholdTypes.BinaryInv);
|
||||
//Show(mat, "Threshold");
|
||||
|
||||
// 侵蚀
|
||||
Cv2.Erode(mat, mat, Cv2.GetStructuringElement(MorphShapes.Rect, new Size(3, 3)));
|
||||
//Show(mat, "Erode");
|
||||
|
||||
// 膨胀
|
||||
Cv2.Dilate(mat, mat, Cv2.GetStructuringElement(MorphShapes.Rect, new Size(3, 3)));
|
||||
//Show(mat, "Dilate");
|
||||
|
||||
return mat;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找图片定位点
|
||||
/// </summary>
|
||||
/// <param name="mat"></param>
|
||||
/// <returns></returns>
|
||||
public IEnumerable<Rect> FindLocationPoint(Mat mat, bool showOutline = false)
|
||||
{
|
||||
List<Rect> rects = new List<Rect>();
|
||||
// 寻找图片轮廓
|
||||
Cv2.FindContours(mat, out Point[][] contours, out HierarchyIndex[] index, RetrievalModes.List, ContourApproximationModes.ApproxSimple);
|
||||
|
||||
foreach (var contour in contours)
|
||||
{
|
||||
if (showOutline)
|
||||
Show(DrawContours(mat, contour));
|
||||
|
||||
//外接矩形
|
||||
var rect = Cv2.BoundingRect(contour);
|
||||
|
||||
// 计算图像内非零像素个数
|
||||
using Mat roi = new Mat(mat, rect);
|
||||
int nonZeroPixels = Cv2.CountNonZero(roi);
|
||||
|
||||
// 计算连通轮廓的面积
|
||||
var area = Cv2.ContourArea(contour);
|
||||
|
||||
// 计算逼近轮廓
|
||||
var approxContour = Cv2.ApproxPolyDP(contour, Cv2.ArcLength(contour, true) * 0.05, true);
|
||||
|
||||
if (Cv2.IsContourConvex(approxContour)
|
||||
&& rect.Width > 10 && rect.Width < 80
|
||||
&& rect.Height > 10 && rect.Height < 80
|
||||
&& area > 200 && area < 3000
|
||||
&& nonZeroPixels > 200)
|
||||
{
|
||||
rects.Add(rect);
|
||||
}
|
||||
}
|
||||
return rects;
|
||||
}
|
||||
|
||||
public Mat DrawContours(Mat mat, Point[] contour)
|
||||
{
|
||||
//转换颜色空间
|
||||
Mat mat_color = new Mat();
|
||||
Cv2.CvtColor(mat, mat_color, ColorConversionCodes.GRAY2BGR);
|
||||
|
||||
Cv2.DrawContours(mat_color, new Point[][] { contour }, -1, Scalar.Red, 2);
|
||||
return mat_color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -7,6 +7,11 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Marking.WebExtensions" Version="1.2.1.4" />
|
||||
<PackageReference Include="OpenCvSharp4" Version="4.9.0.20240103" />
|
||||
<PackageReference Include="OpenCvSharp4.Extensions" Version="4.9.0.20240103" />
|
||||
<PackageReference Include="OpenCvSharp4.runtime.win" Version="4.9.0.20240103" />
|
||||
<PackageReference Include="OpenCvSharp4_.runtime.ubuntu.20.04-x64" Version="4.9.0.20240103" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
|
||||
</ItemGroup>
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,14 @@
|
|||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Qwit;
|
||||
|
||||
namespace Marking.OCR.Service.Packs
|
||||
{
|
||||
[DependsByPack(typeof(MarkingPack))]
|
||||
internal class AppPack : QwitPack
|
||||
{
|
||||
public override void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -1,14 +1,29 @@
|
|||
using Marking;
|
||||
using Marking.OCR.Service.BackgroundServices;
|
||||
using Qwit;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
// Add services to the container.
|
||||
|
||||
builder.Services.AddControllers();
|
||||
builder.Services.AddQwitPack();
|
||||
builder.Services.AddControllers(options =>
|
||||
{
|
||||
// 全局异常捕获,无需在代码中写 try catch
|
||||
options.Filters.Add<ExceptionFilter>();
|
||||
// 全局模型赋值默认值 和 统一返回格式处理
|
||||
options.Filters.Add<ModelActionFilter>();
|
||||
// 全局异地登陆检验
|
||||
//options.Filters.Add<AuthorizationActionFilter>();
|
||||
//全局日志追踪过滤器
|
||||
options.Filters.Add<TraceFilterAttribute>();
|
||||
});
|
||||
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
|
||||
builder.Services.AddEndpointsApiExplorer();
|
||||
builder.Services.AddSwaggerGen();
|
||||
builder.Services.AddHostedService<CheckAndDeleteFilesService>();
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
app.UseQwitPack();
|
||||
// Configure the HTTP request pipeline.
|
||||
if (app.Environment.IsDevelopment())
|
||||
{
|
||||
|
|
|
|||
|
|
@ -6,5 +6,17 @@
|
|||
"ServerNodes": "http://config.23544.com:15000/,http://config.23544.com:15001/", //多个节点使用逗号分隔,
|
||||
"Tag": "marking",
|
||||
"Name": "阅卷后台管理"
|
||||
},
|
||||
"QwitLogServer": {
|
||||
"ServerUrl": "https://log.w.23544.com:8843",
|
||||
"PushKey": "XTPsAhViiJ7rR7/bGM5vH756rD+Uejy8tiuWK/7qEAWRsVj0JqLWm6rpvDWgT322",
|
||||
"CheckServer": false
|
||||
},
|
||||
"WebPack": {
|
||||
"Services": [
|
||||
"Marking.Infrastructure",
|
||||
"Marking.Domain",
|
||||
"Marking.WebExtensions"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 578 KiB |
|
|
@ -0,0 +1,14 @@
|
|||
version: "3"
|
||||
|
||||
services:
|
||||
admin-api:
|
||||
image: ${REGISTRY:-harbor.w.23544.com:8843}/marking/marking.ocr.service:${TAG:-latest}
|
||||
hostname: marking
|
||||
environment:
|
||||
TZ: Asia/Shanghai
|
||||
ASPNETCORE_ENVIRONMENT: ${ASPNETCORE_ENVIRONMENT:-Development} #默认为开发环境
|
||||
ports:
|
||||
- 6555:80
|
||||
deploy:
|
||||
mode: replicated
|
||||
replicas: ${REPLICAS:-1}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<packageSources>
|
||||
<clear />
|
||||
<add key="qwit" value="https://git.h.qwit.top:8843/api/packages/actions/nuget/index.json" />
|
||||
<add key="git" value="https://gitea.23544.com/api/packages/actions/nuget/index.json"/>
|
||||
<add key="marking" value="https://gitea.23544.com/api/packages/marking/nuget/index.json"/>
|
||||
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
|
||||
</packageSources>
|
||||
</configuration>
|
||||
Loading…
Reference in New Issue