c#中WinForm用OpencvSharp實(shí)現(xiàn)ROI區(qū)域提取的示例
已經(jīng)自學(xué)OpencvSharp一段時(shí)間了(目前工作用的是C#,就學(xué)了Opencvsharp了,vs2015,opencvsharp3),收獲也有一些,現(xiàn)在就將我在學(xué)習(xí)過程中的收獲分享出來吧。
圖像處理,很常見的問題,但對(duì)于大多數(shù)時(shí)候而言,我們往往不需要去處理整張圖片,而是只需要處理一部分,這就涉及到了ROI(Region of interest)的提取了。我目前提取ROI的方法是采用掩膜Mask的方法。具體的思路就是:在圖像操作的時(shí)候,定義一張同等大小的空的Mask,也就是全部是0,然后將我們想要的ROI輪廓畫在Mask上,并填充內(nèi)部,就會(huì)得到新的Mask,這個(gè)新的Mask就只有在ROI區(qū)域非0,其余地方元素都是0,再把用Cv2.BoundingRect()將包含ROI區(qū)域的輪廓的最小矩形找出來,分別將原圖與Mask這兩幅圖像的這個(gè)最小矩形部分提出來 ,最后再調(diào)用Cv2.BitwiseAnd()這個(gè)方法,通常情況而言,一副圖像與自己本身進(jìn)行與運(yùn)算,輸出的還是本身圖像,帶上掩膜Mask后,就只會(huì)輸出圖像在Mask非0區(qū)域部分(也就是我們所需要的ROI)的圖像了,這樣就實(shí)現(xiàn)了我們的ROI提取了。
接下來,就分享幾種常見ROI區(qū)域提取吧。
部分代碼如下:
主要使用的變量
/// 放在yVars.ImgOptions中
public struct ROIMatt
{
public static string Image;//原圖
public static bool IsSelectRegion = false;
public static int step; //ROI區(qū)域移動(dòng)步長(zhǎng)
public static int angel; // 旋轉(zhuǎn)一次 angel±=step; 旋轉(zhuǎn)角度
public static yDirections direct = yDirections.NULL;
public static yROIRegionType ROIType = yROIRegionType.Rectangle;
// 矩形ROI
// 矩形四個(gè)點(diǎn)坐標(biāo) 都是相對(duì)于圖像的坐標(biāo) 而不是相對(duì)于picturebox的坐標(biāo)
// 矩形四個(gè)點(diǎn)相對(duì)位置 剛開始確定矩形時(shí)就這樣 經(jīng)過旋轉(zhuǎn)后位置變 但相對(duì)位置還是這樣
// 1 2 // 按順時(shí)針數(shù)的點(diǎn) 1-->2-->4-->3-->1-->2-->4-->3-->1
// 3 4
public static OpenCvSharp.Point rectFirstPoint = new OpenCvSharp.Point();
public static OpenCvSharp.Point rectSecondPoint = new OpenCvSharp.Point();
public static OpenCvSharp.Point rectThirdPoint = new OpenCvSharp.Point();
public static OpenCvSharp.Point rectFourthPoint = new OpenCvSharp.Point();
public static double rectWidth = 0;
public static double rectHeight = 0;
// 圓形ROI
public static OpenCvSharp.Point cirCenter = new OpenCvSharp.Point(0.0,0.0); // 圓心
public static int cirRadious = 0; // 半徑
// 橢圓ROI
public static OpenCvSharp.Point elpCenter = new OpenCvSharp.Point(0.0,0.0); // 橢圓中心點(diǎn)
public static double elpAngel = 0.0;//橢圓傾斜角度
public static double elpLongAxis = 0.0; // 長(zhǎng)軸
public static double elpShortAxis = 0.0; // 短軸
}我的picturebox的SizeMode是StretchImage的,可能看起來跟想要的結(jié)果有點(diǎn)差異,但是實(shí)際上是一樣的。
首先是最常見的矩形。
對(duì)于正矩形而言,我們可以直接定義出圖像的ROI區(qū)域
public Mat(Mat m, Rect roi);
這樣定義的圖像就是原圖m的指定區(qū)域了。但對(duì)于傾斜的矩陣,RotatedRect,而言,就得需要使用掩膜了,提取ROI的方法以及結(jié)果如下:
public static void ImgMattingRect()
{
Mat pic = new Mat(yVars.ImgOptions.ROIMatt.Image);
Mat mask = Mat.Zeros(pic.Size(), MatType.CV_8UC1);
OpenCvSharp.Point2f[] coutours = new OpenCvSharp.Point2f[4];
coutours[0] = yVars.ImgOptions.ROIMatt.rectFirstPoint;
coutours[1] = yVars.ImgOptions.ROIMatt.rectSecondPoint;
coutours[2] = yVars.ImgOptions.ROIMatt.rectFourthPoint;
coutours[3] = yVars.ImgOptions.ROIMatt.rectThirdPoint;
List<OpenCvSharp.Point> listt = new List<OpenCvSharp.Point>();
for (int i = 0; i < coutours.Count(); i++)
{
listt.Add(new OpenCvSharp.Point(coutours[i].X, coutours[i].Y));
}
List<List<OpenCvSharp.Point>> pp = new List<List<OpenCvSharp.Point>>() { listt };
Cv2.FillPoly(mask, pp, new Scalar(255, 255, 255));
OpenCvSharp.Rect rect = Cv2.BoundingRect(coutours);
Mat src = new Mat(pic, rect);
Mat maskROI = new Mat(mask, rect);
Mat picOut = new Mat();
Cv2.BitwiseAnd(src, src, picOut, maskROI);
Form1.Instance.pbxMattImage.Image = yImgConvert.MatToBitmap(picOut);
yVars.ImgOptions.ROIMatt.rectFirstPoint = new OpenCvSharp.Point(0, 0);
yVars.ImgOptions.ROIMatt.rectSecondPoint = new OpenCvSharp.Point(0, 0);
yVars.ImgOptions.ROIMatt.rectThirdPoint = new OpenCvSharp.Point(0, 0);
yVars.ImgOptions.ROIMatt.rectFourthPoint = new OpenCvSharp.Point(0, 0);
}
縮放平移和旋轉(zhuǎn)就只要改變矩形的四個(gè)頂點(diǎn)坐標(biāo)就行了。方法都一樣就不贅述了。
圓形ROI區(qū)域,
方法如下:
public static void ImgMattingCircle()
{
Mat mm = new Mat(yVars.ImgOptions.ROIMatt.Image);
Mat mask = Mat.Zeros(mm.Size(), MatType.CV_8UC3);
Cv2.Circle(mask, yVars.ImgOptions.ROIMatt.cirCenter, yVars.ImgOptions.ROIMatt.cirRadious, Scalar.Red, 1, LineTypes.AntiAlias);
Cv2.FloodFill(mask, yVars.ImgOptions.ROIMatt.cirCenter, Scalar.Red);
mask.ConvertTo(mask, MatType.CV_8UC1);
int xx = yVars.ImgOptions.ROIMatt.cirCenter.X - yVars.ImgOptions.ROIMatt.cirRadious;
int yy = yVars.ImgOptions.ROIMatt.cirCenter.Y - yVars.ImgOptions.ROIMatt.cirRadious;
int rr = 2 * yVars.ImgOptions.ROIMatt.cirRadious;
// 圓的外接正方形
Rect rect = new Rect(new OpenCvSharp.Point(xx, yy), new OpenCvSharp.Size(rr, rr));
Mat src = new Mat(mm, rect);
Mat maskRoI = new Mat(mask, rect);
Cv2.CvtColor(maskRoI, maskRoI, ColorConversionCodes.BGR2GRAY);
Mat picOut = new Mat();
Cv2.BitwiseAnd(src, src, picOut, maskRoI);
Form1.Instance.pbxMattImage.Image = yImgConvert.MatToBitmap(picOut);
yVars.ImgOptions.ROIMatt.cirCenter = new OpenCvSharp.Point(0, 0);
yVars.ImgOptions.ROIMatt.cirRadious = 0;
}效果展示:

圓形ROI的移動(dòng)時(shí)就只有圓心坐標(biāo)變 半徑不變,而縮放時(shí)只改變半徑,圓心不變,注意移動(dòng)時(shí)別超出圖像界限就行。
橢圓ROI
在Opencvsharp中繪制橢圓有兩種方式
//
// 摘要:
// Draws simple or thick elliptic arc or fills ellipse sector
//
// 參數(shù):
// img:
// Image.
//
// box:
// The enclosing box of the ellipse drawn
//
// color:
// Ellipse color.
//
// thickness:
// Thickness of the ellipse boundary. [By default this is 1]
//
// lineType:
// Type of the ellipse boundary. [By default this is LineType.Link8]
public static void Ellipse(InputOutputArray img, RotatedRect box, Scalar color, int thickness = 1, LineTypes lineType = LineTypes.Link8);
//
// 摘要:
// Draws simple or thick elliptic arc or fills ellipse sector
//
// 參數(shù):
// img:
// Image.
//
// center:
// Center of the ellipse.
//
// axes:
// Length of the ellipse axes.
//
// angle:
// Rotation angle.
//
// startAngle:
// Starting angle of the elliptic arc.
//
// endAngle:
// Ending angle of the elliptic arc.
//
// color:
// Ellipse color.
//
// thickness:
// Thickness of the ellipse arc. [By default this is 1]
//
// lineType:
// Type of the ellipse boundary. [By default this is LineType.Link8]
//
// shift:
// Number of fractional bits in the center coordinates and axes' values. [By default
// this is 0]
public static void Ellipse(InputOutputArray img, Point center, Size axes, double angle, double startAngle, double endAngle, Scalar color, int thickness = 1, LineTypes lineType = LineTypes.Link8, int shift = 0);我們采用第一種方式,即可以將橢圓轉(zhuǎn)化成一個(gè)RotatedRect,只要在畫RotatedRect的時(shí)候改成畫橢圓即可,就可以回到第一種矩形的ROI提取上面了, 代碼如下:
public static void ImgMattingEllipse()
{
Mat mm = new Mat(yVars.ImgOptions.ROIMatt.Image);
Mat mask = Mat.Zeros(mm.Size(), MatType.CV_8UC3);
RotatedRect rorect = new RotatedRect(yVars.ImgOptions.ROIMatt.elpCenter, new Size2f(yVars.ImgOptions.ROIMatt.elpLongAxis, yVars.ImgOptions.ROIMatt.elpShortAxis), (float)yVars.ImgOptions.ROIMatt.elpAngel);
Cv2.Ellipse(mask, rorect, Scalar.Red);
Mat gray = new Mat();
Cv2.CvtColor(mask, gray, ColorConversionCodes.BGR2GRAY);
Cv2.Threshold(gray, gray, 100, 255, ThresholdTypes.Otsu);
OpenCvSharp.Point[][] contours;
HierarchyIndex[] hierarchly;
Cv2.FindContours(gray, out contours, out hierarchly, RetrievalModes.Tree, ContourApproximationModes.ApproxSimple, new OpenCvSharp.Point(0, 0));
Rect rect = Cv2.BoundingRect(contours[0]);
Cv2.FloodFill(mask, yVars.ImgOptions.ROIMatt.elpCenter, Scalar.Red);
mask.ConvertTo(mask, MatType.CV_8UC1);
Mat src = new Mat(mm, rect);
Mat maskRoI = new Mat(mask, rect);
Cv2.CvtColor(maskRoI, maskRoI, ColorConversionCodes.BGR2GRAY);
Mat picOut = new Mat();
Cv2.BitwiseAnd(src, src, picOut, maskRoI);
Form1.Instance.pbxMattImage.Image = yImgConvert.MatToBitmap(picOut);
}實(shí)驗(yàn)結(jié)果如下:

平移縮放旋轉(zhuǎn)等操作就可以看成對(duì)RotatedRect的操作即可。
到此這篇關(guān)于c#中WinForm用OpencvSharp實(shí)現(xiàn)ROI區(qū)域提取的示例的文章就介紹到這了,更多相關(guān)c# ROI區(qū)域提取內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C#基于FTP協(xié)議的簡(jiǎn)易軟件自動(dòng)升級(jí)程序
這篇文章主要為大家詳細(xì)介紹了C#基于FTP協(xié)議的簡(jiǎn)易軟件自動(dòng)升級(jí)程序,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-03-03
使用C#開發(fā)OPC?Server服務(wù)器源碼解析
OPC?Server服務(wù)器服務(wù)器的開發(fā)比較繁瑣,本示例采用C#提供了一種簡(jiǎn)單快速實(shí)現(xiàn)OPCServer的方法,已經(jīng)在工程項(xiàng)目中應(yīng)用,本文對(duì)C#開發(fā)OPC?Server服務(wù)器相關(guān)知識(shí)給大家介紹的非常詳細(xì),需要的朋友參考下吧2022-06-06

