else if (pDoc.RunCamera1 && data.Tool == "Khiem" || data.Tool == "Khiem" && nowStep <= pDoc.CurrentStep[0])
string[] parts = data.Spec.Split(',');
if (parts[0] == "Original")
Src = inputImage.Clone();
else if (parts[0] == "Beforehand")
Src = outputImage.Clone();
Src = LoadImageRegions(parts[0]);
Vec3b bgPixel = Src.At<Vec3b>(0, 0);
Scalar baseColor = new Scalar(bgPixel.Item0, bgPixel.Item1, bgPixel.Item2);
Scalar lower = new Scalar(
Math.Max(baseColor.Val0 - delta, 0),
Math.Max(baseColor.Val1 - delta, 0),
Math.Max(baseColor.Val2 - delta, 0)
Scalar upper = new Scalar(
Math.Min(baseColor.Val0 + delta, 255),
Math.Min(baseColor.Val1 + delta, 255),
Math.Min(baseColor.Val2 + delta, 255)
Cv2.InRange(Src, lower, upper, mask);
foreach (var rect in new[]
new Rect(0, 0, 100, 100),
new Rect(Src.Cols - 100, 0, 100, 100),
new Rect(0, Src.Rows - 100, 100, 100),
new Rect(Src.Cols - 100, Src.Rows - 100, 100, 100)
Cv2.Rectangle(mask, rect, new Scalar(255), -1);
Cv2.BitwiseNot(mask, mask);
Cv2.CvtColor(mask, Src, ColorConversionCodes.GRAY2BGR);
HierarchyIndex[] hierarchy;
Cv2.FindContours(mask, out contours, out hierarchy, RetrievalModes.External, ContourApproximationModes.ApproxSimple);
var sortedContours = contours
.Select(c => new { contour = c, area = Cv2.ContourArea(c), rect = Cv2.BoundingRect(c) })
.Where(c => c.area > 100)
.OrderByDescending(c => c.area)
foreach (var item in sortedContours)
Cv2.DrawContours(Src, new[] { item.contour }, -1, new Scalar(0, 255, 0), 4);
Cv2.PutText(Src, $"#{idx++}", new Point(item.rect.X, item.rect.Y - 10), HersheyFonts.HersheySimplex, 1.0, Scalar.Red, 2);
bool foundShapeMatch = false;
for (int i = 0; i < sortedContours.Count; i++)
for (int j = i + 1; j < sortedContours.Count; j++)
var c1 = sortedContours[i].contour;
var c2 = sortedContours[j].contour;
double score = Cv2.MatchShapes(c1, c2, ShapeMatchModes.I1, 0);
Cv2.Rectangle(Src, sortedContours[i].rect, new Scalar(0, 255, 255), 6);
Cv2.Rectangle(Src, sortedContours[j].rect, new Scalar(0, 255, 255), 6);
if (foundShapeMatch) break;
outputImage = Src.Clone();
pDoc.ChuoiGuiClient1 = "OK";
Console.WriteLine($"[Khiem] Found contours: {contours.Length} | Matching shape: {foundShapeMatch}");