Last active
August 13, 2020 12:56
-
-
Save synctam/1345430efe0fae1cd6f86fa7d076c543 to your computer and use it in GitHub Desktop.
OpenCVで輪郭検出を行いテキスト領域を抽出するサンプル。 This program is released under the MIT license.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace LibTextDetector.TextDetector | |
{ | |
using System; | |
using System.Collections.Generic; | |
using System.Diagnostics; | |
using System.Drawing; | |
using System.Linq; | |
using System.Text; | |
using System.Threading.Tasks; | |
using Emgu.CV; | |
using Emgu.CV.Structure; | |
public class GcaTextDetector | |
{ | |
/// <summary> | |
/// 指定した画像からテキスト領域のリストを返す。 | |
/// (輪郭検出を利用しテキスト領域を抽出) | |
/// </summary> | |
/// <param name="img">画像</param> | |
/// <returns>テキスト領域のリスト</returns> | |
public static List<Rectangle> DetectText(Image<Bgr, byte> img) | |
{ | |
//// sobel(エッジ抽出) | |
Image<Gray, byte> sobel = | |
img | |
.Convert<Gray, byte>() | |
.Sobel(1, 0, 3) | |
.AbsDiff(new Gray(0.0)) | |
.Convert<Gray, byte>() | |
.ThresholdBinary(new Gray(100), new Gray(255)); | |
//// | |
Mat se = CvInvoke.GetStructuringElement( | |
Emgu.CV.CvEnum.ElementShape.Rectangle, | |
new Size(10, 2), | |
new Point(-1, -1)); | |
//// | |
sobel = sobel.MorphologyEx( | |
Emgu.CV.CvEnum.MorphOp.Dilate, | |
se, | |
new Point(-1, -1), | |
1, | |
Emgu.CV.CvEnum.BorderType.Reflect, | |
new MCvScalar(255)); | |
//// 輪郭検出 | |
var contours = new Emgu.CV.Util.VectorOfVectorOfPoint(); | |
var m = new Mat(); | |
CvInvoke.FindContours( | |
sobel, | |
contours, | |
m, | |
Emgu.CV.CvEnum.RetrType.External, | |
Emgu.CV.CvEnum.ChainApproxMethod.ChainApproxSimple); | |
//// テキストラインの矩形領域のリスト | |
var list = new List<Rectangle>(); | |
for (int i = 0; i < contours.Size; i++) | |
{ | |
var brect = CvInvoke.BoundingRectangle(contours[i]); | |
//// 矩形領域を条件に従い抽出する | |
double ar = brect.Width / brect.Height; | |
if (ar > 2 && brect.Width > 25 && brect.Height > 5 && brect.Height < 100) | |
{ | |
//// 領域の縦横比が1:2。2文字以上? | |
//// 領域の幅が > 25 pixel | |
//// 5 pixel < 領域の高さ < 100 | |
list.Add(brect); | |
} | |
} | |
//// X > Y でソート | |
IOrderedEnumerable<Rectangle> sortList = list.OrderBy(rec => rec.Y).ThenBy(rec => rec.X); | |
List<Rectangle> result = new List<Rectangle>(); | |
foreach (var aaa in sortList) | |
{ | |
result.Add(aaa); | |
} | |
return result; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace LibTextDetector.TextDetector | |
{ | |
using Emgu.CV; | |
using Emgu.CV.Structure; | |
using LibTextDetector.Ocr; | |
using System; | |
using System.Collections.Generic; | |
using System.Diagnostics; | |
using System.Drawing; | |
using System.Linq; | |
using System.Text; | |
using System.Threading.Tasks; | |
public class GcaVideoEffector | |
{ | |
public static List<string> GetImageToTexts(string imagePath, string outImagePath) | |
{ | |
Image<Bgr, byte> img = new Image<Bgr, byte>(imagePath); | |
var regions = GcaTextDetector.DetectText(img); | |
var ocr = new GcaOcr(); | |
var result = ocr.GetText(img, regions); | |
var outImage = TextDetectedImage(img, regions); | |
outImage.Save(outImagePath); | |
return result; | |
} | |
public static double Process(string inputVideoPath, string outputVideoPath) | |
{ | |
Stopwatch sw = new Stopwatch(); | |
double max = 0.0f; | |
//// @"data\Eschalon_ Book I_001.mp4" | |
var capture = new VideoCapture(inputVideoPath); | |
var fps = capture.GetCaptureProperty(Emgu.CV.CvEnum.CapProp.Fps); | |
System.Drawing.Size size = new System.Drawing.Size(capture.Width, capture.Height); | |
int fourcc = VideoWriter.Fourcc('H', '2', '6', '4'); | |
Backend[] backends = CvInvoke.WriterBackends; | |
int backend_idx = 0; | |
foreach (Backend be in backends) | |
{ | |
if (be.Name.Equals("MSMF")) | |
{ | |
backend_idx = be.ID; | |
break; | |
} | |
} | |
var writer = new VideoWriter(outputVideoPath, backend_idx, fourcc, fps, size, true); | |
var ocr = new GcaOcr(); | |
try | |
{ | |
while (true) | |
{ | |
var m = new Mat(); | |
capture.Read(m); | |
if (!m.IsEmpty) | |
{ | |
var img = m.ToImage<Bgr, byte>(); | |
sw.Start(); | |
var regions = GcaTextDetector.DetectText(img); | |
sw.Stop(); | |
max = Math.Max(max, sw.ElapsedMilliseconds); | |
sw.Reset(); | |
List<string> textList = ocr.GetText(img, regions); | |
Image<Bgr, byte> imgout = img.CopyBlank(); | |
foreach (var r in regions) | |
{ | |
CvInvoke.Rectangle(img, r, new MCvScalar(0, 0, 255), 2); | |
CvInvoke.Rectangle(imgout, r, new MCvScalar(0, 255, 255), -1); | |
} | |
imgout._And(img); | |
writer.Write(img.Mat); | |
} | |
else | |
{ | |
break; | |
} | |
} | |
} | |
finally | |
{ | |
writer.Dispose(); | |
} | |
return max; | |
} | |
/// <summary> | |
/// テキスト検出結果のイメージを返す。 | |
/// </summary> | |
/// <param name="img">元イメージ</param> | |
/// <param name="regions">テキスト領域のリスト</param> | |
/// <returns>テキスト検出結果のイメージ</returns> | |
private static Image<Bgr, byte> TextDetectedImage(Image<Bgr, byte> img, List<Rectangle> regions) | |
{ | |
Image<Bgr, byte> imgout = img.CopyBlank(); | |
foreach (var r in regions) | |
{ | |
CvInvoke.Rectangle(img, r, new MCvScalar(0, 0, 255), 2); | |
CvInvoke.Rectangle(imgout, r, new MCvScalar(0, 255, 255), -1); | |
} | |
imgout._And(img); | |
return imgout; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment