<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12
      【Talk is cheap. Show me the code.】 公眾號如有回復不及時的,麻煩點擊聯系關于我-聯系博主,微信我。謝謝!
      老帥哥

      Stephen-kzx的博客

      【Talk is cheap. Show me the code.】【公眾號如有回復不及時的,麻煩點擊聯系關于我-聯系博主,微信我。謝謝!】

      OpenCvSharp基于顏色反差規避FBA面單貼標

      01

      規避原理

      1.摳圖,根據色差或者根據固定包裹位置以及包裹尺寸摳出紙箱圖片

      2.色差,獲取紙箱上所有背景色的灰度值

      3.采圖,采集大量視野相同,光源相同面單的色差灰度值,整理區間

      4.取反,所有非面單灰度值區間的,都認為是紙箱背景色

      02
      1. 根據DPI計算1mm對應像素點。

      2. 獲取吸取的顏色,計算灰度值

       

      // 300 DPI 計算:每毫米像素數 = 300 / 25.4 ≈ 11.81
      private const double PixelsPerMm = 300.0 / 25.4 ;
      private static int LabelSizePixels = Convert.ToInt32(Math.Ceiling((int)(95 * PixelsPerMm) / 1.7)); // 100mm × 100mm

      // 面單顏色列表(十六進制格式)
      private static readonly List<string> LabelColors = new List<string>
      {
      "#E2E2E0", "#DEDEDC", "#E0E0DE", "#CCCCCA", "#B2B2B0", "#C2C2C0","#FFFFFF","#FEFEFE","#FCFCFC" ,"#ADADAD"
      };

      // 計算出的面單灰度范圍
      private static int MinLabelGray;
      private static int MaxLabelGray;
      // 加載圖像
      var originalImage = Cv2.ImRead(@"D:\Users\steph\Pictures\1分4\Image_20250913210539498.jpg", OpenCvSharp.ImreadModes.Grayscale);

      // 計算面單灰度范圍
      CalculateLabelGrayRange();
      Console.WriteLine($"計算出的面單灰度范圍: {MinLabelGray}-{MaxLabelGray}");


      if (originalImage.Empty())
      {
      Console.WriteLine("無法加載圖像");
      return;
      }

      此處用第二種最簡單方式演示,視野固定包裹位置,根據計算包裹的尺寸,扣除原箱外觀

      // 從右下角裁剪圖像
      private static OpenCvSharp.Mat CropImageFromBottomRight(OpenCvSharp.Mat image, double widthMm, double heightMm)
      {
      // 將毫米轉換為像素
      int widthPixels = (int)(widthMm * PixelsPerMm/1.7);
      int heightPixels = (int)(heightMm * PixelsPerMm/1.7);

      // 獲取圖像尺寸
      int imgWidth = image.Cols;
      int imgHeight = image.Rows;

      // 計算裁剪區域的左上角坐標
      int x = Math.Max(0, imgWidth - widthPixels);
      int y = Math.Max(0, imgHeight - heightPixels);

      // 確保裁剪區域不超出圖像邊界
      widthPixels = Math.Min(widthPixels, imgWidth - x);
      heightPixels = Math.Min(heightPixels, imgHeight - y);

      // 檢查裁剪區域是否有效
      if (widthPixels <= 0 || heightPixels <= 0)
      {
      Console.WriteLine($"無效的裁剪區域: x={x}, y={y}, width={widthPixels}, height={heightPixels}");
      return image.Clone(); // 返回原始圖像的副本
      }

      Console.WriteLine($"裁剪區域: x={x}, y={y}, width={widthPixels}, height={heightPixels}");

      // 裁剪圖像
      return new OpenCvSharp.Mat(image, new Rect(x, y, widthPixels, heightPixels));
      }

      根據裁切后的原箱外觀,以及灰度值區間,定位原廠面單位置

      // 檢測所有原廠面單位置
      public static List<LabelPosition> DetectOriginalLabelPositions(OpenCvSharp.Mat image)
      {
      var labelPositions = new List<LabelPosition>();

      // 二值化圖像以分離面單區域
      var binary = new OpenCvSharp.Mat();
      Cv2.Threshold(image, binary, MinLabelGray, 255, ThresholdTypes.Binary);

      // 形態學操作去除噪聲
      var kernel = Cv2.GetStructuringElement(MorphShapes.Rect, new OpenCvSharp.Size(5, 5));
      Cv2.MorphologyEx(binary, binary, MorphTypes.Open, kernel);

      // 查找輪廓
      Cv2.FindContours(binary, out var contours, out _, RetrievalModes.External, ContourApproximationModes.ApproxSimple);

      // 過濾輪廓(按面積)
      var filteredContours = contours.Where(c => Cv2.ContourArea(c) > 1000).ToList();

      // 處理每個輪廓
      foreach (var contour in filteredContours)
      {
      // 獲取輪廓的邊界矩形
      var rect = Cv2.BoundingRect(contour);

      // 轉換為網格坐標
      string gridCoordinate = ConvertToGridCoordinate(rect, image.Rows, image.Cols);

      // 計算實際尺寸(毫米)
      double widthMm = rect.Width / PixelsPerMm;
      double heightMm = rect.Height / PixelsPerMm;

      // 添加到結果列表
      labelPositions.Add(new LabelPosition
      {
      Rect = rect,
      GridCoordinate = gridCoordinate,
      WidthMm = widthMm,
      HeightMm = heightMm
      });
      }

      return labelPositions;
      }

      檢查可貼標簽位置是否與原廠標簽有交集,檢查可貼區域是否超過原箱尺寸,此處我們以新帖面單大小100mm*100mm為例。沒有可貼標簽位置默認選擇1-1位置貼標

      // 查找可貼標簽的位置(與原廠標簽無交集的網格)
      public static List<string> FindAvailableLabelPositions(OpenCvSharp.Mat image, List<LabelPosition> labelPositions)
      {
      	var availablePositions = new List<string>();
      
      	// 獲取圖像尺寸
      	int rows = image.Rows;
      	int cols = image.Cols;
      
      	// 計算網格行列數
      	int gridCols = (int)Math.Ceiling((double)cols / LabelSizePixels);
      	int gridRows = (int)Math.Ceiling((double)rows / LabelSizePixels);
      
      	// 檢查每個網格位置是否可用
      	for (int row = 1; row <= gridRows; row++)
      	{
      		for (int col = 1; col <= gridCols; col++)
      		{
      			// 計算當前網格的像素坐標
      			int x1 = Math.Max(0, cols - col * LabelSizePixels);
      			int y1 = Math.Max(0, rows - row * LabelSizePixels);
      			int x2 = Math.Min(cols, x1 + LabelSizePixels);
      			int y2 = Math.Min(rows, y1 + LabelSizePixels);
      
      			// 確保區域足夠大
      			if (x2 - x1 < LabelSizePixels / 2 || y2 - y1 < LabelSizePixels / 2)
      				continue;
      
      			// 創建網格矩形
      			Rect gridRect = new Rect(x1, y1, x2 - x1, y2 - y1);
      
      			// 檢查網格是否與任何原廠標簽相交
      			bool intersects = false;
      			foreach (var labelPos in labelPositions)
      			{
      				if (gridRect.IntersectsWith(labelPos.Rect))
      				{
      					intersects = true;
      					break;
      				}
      			}
      
      			// 如果不相交且區域顏色均勻,則添加到可用位置
      			if (!intersects && IsAreaUniform(image, x1, y1, x2, y2))
      			{
      				availablePositions.Add($"{row}-{col}");
      			}
      		}
      	}
      
      	return availablePositions;
      }
      

        

       

      可視化結果,以綠色網格鋪滿原箱,以紅色區域標定原廠標簽位置,以藍色網格標定可貼標簽位置,返回可視化結果

      // 可視化結果
      public static OpenCvSharp.Mat VisualizeResults(OpenCvSharp.Mat image, List<LabelPosition> labelPositions, List<string> availablePositions)
      {
      	var colorImage = new OpenCvSharp.Mat();
      	Cv2.CvtColor(image, colorImage, ColorConversionCodes.GRAY2BGR);
      
      	int rows = image.Rows;
      	int cols = image.Cols;
      
      	// 繪制網格
      	for (int x = 0; x < cols; x += LabelSizePixels)
      	{
      		Cv2.Line(colorImage, new OpenCvSharp.Point(x, 0), new OpenCvSharp.Point(x, rows), Scalar.Green, 2);
      	}
      	for (int y = 0; y < rows; y += LabelSizePixels)
      	{
      		Cv2.Line(colorImage, new OpenCvSharp.Point(0, y), new OpenCvSharp.Point(cols, y), Scalar.Green, 2);
      	}
      
      	// 標記所有原廠面單位置(紅色)
      	foreach (var labelPos in labelPositions)
      	{
      		Cv2.Rectangle(colorImage,
      					 labelPos.Rect.TopLeft,
      					 labelPos.Rect.BottomRight,
      					 Scalar.Red, 2);
      
      		// 添加標簽文本
      		Cv2.PutText(colorImage,
      				   labelPos.GridCoordinate,
      				   new OpenCvSharp.Point(labelPos.Rect.X, labelPos.Rect.Y - 5),
      				   HersheyFonts.HersheySimplex,
      				   0.5,
      				   Scalar.Red,
      				  2);
      	}
      
      	// 標記可貼標簽位置(藍色)
      	foreach (var pos in availablePositions)
      	{
      		var parts = pos.Split('-');
      		if (parts.Length != 2) continue;
      
      		int row = int.Parse(parts[0]);
      		int col = int.Parse(parts[1]);
      
      		int x = Math.Max(0, cols - col * LabelSizePixels);
      		int y = Math.Max(0, rows - row * LabelSizePixels);
      		int width = Math.Min(LabelSizePixels, cols - x);
      		int height = Math.Min(LabelSizePixels, rows - y);
      
      		if (width > 0 && height > 0)
      		{
      			Cv2.Rectangle(colorImage,
      						 new OpenCvSharp.Point(x, y),
      						 new OpenCvSharp.Point(x + width, y + height),
      						 Scalar.Blue, 2);
      
      			// 添加標簽文本
      			Cv2.PutText(colorImage,
      					   pos,
      					   new OpenCvSharp.Point(x + 5, y + 15),
      					   HersheyFonts.HersheySimplex,
      					   0.4,
      					   Scalar.Blue,
      					   1);
      		}
      	} 
      	return colorImage;
      }
      

        

       

      看看效果1,運行看看效果.(如下圖紙箱長400,高190)白色原廠面單占據了前面6個網格,最后兩個網格超過原箱尺寸無效,默認返回第一個網格(視情況自定義)

      v2-76bea0c4e881e9a78fe493e220a4571c_1440w

       

      保持期待 奔赴山海KEEP LOOKING FORWARD TO GOING

      效果2.原廠標簽占據第一個和中間4個網格,可貼標簽區域藍色網格標識,并返回可貼坐標

      v2-93076877ffd4cc6bd8ea3897aeabc155_1440w

       

      posted @ 2025-09-19 01:48  何以解憂唯有*碼  閱讀(240)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 国内精品免费久久久久电影院97| 99www久久综合久久爱com| 天天躁日日躁狠狠躁2018| 国产福利酱国产一区二区| 国内精品久久久久久久97牛牛| 狠狠色综合久久丁香婷婷| 国产一区二区三区免费观看| 成人精品色一区二区三区| 99久久精品国产一区二区蜜芽| 国产精品无码专区| 免费 黄 色 人成 视频 在 线| 久久99精品久久久久麻豆| 一区二区三区日本久久九| 日韩高清国产中文字幕| 国产乱人对白| 熟女一区| 三人成全免费观看电视剧高清| 熟女激情乱亚洲国产一区| 国语自产少妇精品视频蜜桃| 亚洲免费视频一区二区三区| 日韩精品一区二区三区激| 国内揄拍国内精品对久久| 亚洲一二三区精品美妇| 少妇人妻偷人精品无码视频新浪| 国内精品视这里只有精品| 婷婷综合久久中文字幕| 国产精品三级中文字幕| 亚洲av伊人久久综合性色| 无码人妻一区二区三区av| 亚洲精品国产精品乱码不卡| 人妻少妇偷人无码视频| 亚洲欧美综合人成在线| 亚洲婷婷综合色香五月| 亚洲一区在线成人av| 成人片黄网站色大片免费毛片| 韩国午夜理伦三级| 国产拍拍拍无码视频免费 | 国产高清在线A免费视频观看| 99亚洲男女激情在线观看| 亚洲AV成人一区国产精品| 国产亚洲精品午夜福利|