OpenCV - EAST Text Detection 테스트
관련 소스코드를 참조하여 코딩했습니다.
OpenCvSharp 패키지를 설치하고 Models/frozen_east_text_detection.pb
가 있어야 합니다
EAST Text Detection Model 다운로드

![image]()
![image]()
using OpenCvSharp;
using OpenCvSharp.Dnn;
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Net.Http;
//var imageUri = "https://ganpaneasy.co.kr/uploads/cmallitem/2020/01/1d9a6d44adfe9b20bcbfb964b822be98.jpg";
var imageUri = "https://t1.daumcdn.net/thumb/R720x0/?fname=http://t1.daumcdn.net/brunch/service/user/3FXy/image/sqSmOMklFK34ylouQhXl08CPenw.png";
using var net = CvDnn.ReadNet("./Models/frozen_east_text_detection.pb");
using var c = new HttpClient();
var imageData = await c.GetByteArrayAsync(imageUri);
using var frame = Mat.FromImageData(imageData);
var (newW, newH) = (320, 320);
var rW = (float)frame.Width / newW;
var rH = (float)frame.Height / newH;
var newFrame = frame.Resize(new Size(newW, newH));
//Window.ShowImages(newFrame);
using var blob = CvDnn.BlobFromImage(newFrame, 1.0, new Size(newFrame.Width, newFrame.Height), new Scalar(123.68, 116.78, 103.94), swapRB: true, crop: false);
var outputLayers = new[] { "feature_fusion/Conv_7/Sigmoid", "feature_fusion/concat_3" };
net.SetInput(blob);
var output = new List<Mat>() { new(), new() };
net.Forward(output, outputLayers);
var scores = output[0];
var geometry = output[1];
var numRows = scores.Rows;
var numCols = scores.Cols;
var confThreshold = 0.5f;
Decode(scores, geometry, confThreshold, out var boxes, out var confidences);
var nmsThreshold = 0.4f;
CvDnn.NMSBoxes(boxes, confidences, confThreshold, nmsThreshold, out var indices);
// Render detections.
var ratio = new Point2f(rW, rH);
for (var i = 0; i < indices.Length; ++i)
{
RotatedRect box = boxes[indices[i]];
Point2f[] vertices = box.Points();
for (int j = 0; j < 4; ++j)
{
vertices[j].X *= ratio.X;
vertices[j].Y *= ratio.Y;
}
for (int j = 0; j < 4; ++j)
{
Cv2.Line(frame, (int)vertices[j].X, (int)vertices[j].Y, (int)vertices[(j + 1) % 4].X, (int)vertices[(j + 1) % 4].Y, new Scalar(0, 255, 0), 3);
}
}
// Optional - Save detections
var fileName = "output.jpg";
frame.SaveImage(Path.Combine(Path.GetDirectoryName(fileName), $"{Path.GetFileNameWithoutExtension(fileName)}_east.jpg"));
// -------------
static unsafe void Decode(Mat scores, Mat geometry, float confThreshold, out IList<RotatedRect> boxes, out IList<float> confidences)
{
boxes = new List<RotatedRect>();
confidences = new List<float>();
if ((scores == null || scores.Dims != 4 || scores.Size(0) != 1 || scores.Size(1) != 1) ||
(geometry == null || geometry.Dims != 4 || geometry.Size(0) != 1 || geometry.Size(1) != 5) ||
(scores.Size(2) != geometry.Size(2) || scores.Size(3) != geometry.Size(3)))
{
return;
}
int height = scores.Size(2);
int width = scores.Size(3);
for (int y = 0; y < height; ++y)
{
var scoresData = new ReadOnlySpan<float>((void*)scores.Ptr(0, 0, y), height);
var x0Data = new ReadOnlySpan<float>((void*)geometry.Ptr(0, 0, y), height);
var x1Data = new ReadOnlySpan<float>((void*)geometry.Ptr(0, 1, y), height);
var x2Data = new ReadOnlySpan<float>((void*)geometry.Ptr(0, 2, y), height);
var x3Data = new ReadOnlySpan<float>((void*)geometry.Ptr(0, 3, y), height);
var anglesData = new ReadOnlySpan<float>((void*)geometry.Ptr(0, 4, y), height);
for (int x = 0; x < width; ++x)
{
var score = scoresData[x];
if (score >= confThreshold)
{
float offsetX = x * 4.0f;
float offsetY = y * 4.0f;
float angle = anglesData[x];
float cosA = (float)Math.Cos(angle);
float sinA = (float)Math.Sin(angle);
float x0 = x0Data[x];
float x1 = x1Data[x];
float x2 = x2Data[x];
float x3 = x3Data[x];
float h = x0 + x2;
float w = x1 + x3;
Point2f offset = new Point2f(offsetX + (cosA * x1) + (sinA * x2), offsetY - (sinA * x1) + (cosA * x2));
Point2f p1 = new Point2f((-sinA * h) + offset.X, (-cosA * h) + offset.Y);
Point2f p3 = new Point2f((-cosA * w) + offset.X, (sinA * w) + offset.Y);
RotatedRect r = new RotatedRect(new Point2f(0.5f * (p1.X + p3.X), 0.5f * (p1.Y + p3.Y)), new Size2f(w, h), (float)(-angle * 180.0f / Math.PI));
boxes.Add(r);
confidences.Add(score);
}
}
}
}