锐单电子商城 , 一站式电子元器件采购平台!
  • 电话:400-990-0325

opencv 最大内接矩形笔记

时间:2023-02-01 12:00:00 连接器矩形重载热流插头ha矩形连接器y27g矩形连接器lcaxn500

python 最小外部矩形

最小外部矩形的顶点坐标:cv2.boxPoints

        cnt = np.array([[data_0_x, data_0_y], [data_1_x, data_1_y], [data_2_x, data_2_y], [data_3_x, data_3_y]])  # 必须是array数组的形式         rect = cv2.minAreaRect(cnt)  # 获得最小外部矩形(中心(x,y), (宽,高), 旋转角度)         box = cv2.boxPoints(rect)  # 获得最小外部矩形的4个顶点坐标         box = np.int0(box)         cv2.drawContours(img, [box], 0, (255, 0, 0), 1)

轮廓矩形框:

 cnt = np.array([[data_0_x, data_0_y], [data_1_x, data_1_y], [data_2_x, data_2_y], [data_3_x, data_3_y]])  # 必须是array数组的形式 ret=cv2.boundingRect(cnt) x,y,w,h=ret

最大内部矩形,从轮廓中的所有坐标中获得四个坐标:

python 获取过程如下:

转移:图像轮廓最大的内部矩形 - 奥布莱恩 - 博客园

def order_points(pts):     # pts为轮廓坐标     # 列表中的存储元素分别是左上角、右上角、右下角和左下角     rect = np.zeros((4, 2), dtype = "float32")     # 左上角的点有最小和,右下角的点有最大的和     s = pts.sum(axis = 1)     rect[0] = pts[np.argmin(s)]     rect[2] = pts[np.argmax(s)]     # 计算点之间的差值     # 右上角的点差最小,     # 左下角的点差最大     diff = np.diff(pts, axis = 1)     rect[1] = pts[np.argmin(diff)]     rect[3] = pts[np.argmax(diff)]     # 返回排序坐标(左上右下左下)     return rect    img = cv2.imread(path) gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) blurred = cv2.blur(gray, (9, 9)) _, thresh = cv2.threshold(blurred, 155, 255, cv2.THRESH_BINARY) _, cnts, _ = cv2.findContours( thresh.copy(), cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE) c = sorted(cnts, key=cv2.contourArea, reverse=True)[0]
首先找出轮廓点 rect = order_points(c.reshape(c.shape[0], 2)) print(rect) xs = [i[0] for i in rect] ys = [i[1] for i in rect] xs.sort() ys.sort() #内接矩形坐标为 print(xs[1],xs[2],ys[1],ys[2])

一下内容转自:

python-opencv 图像捕捉多个不规则的轮廓,与轮廓内部区域(圆/矩形)的想法持续更新编辑(详细的想法解释和图片将附加) - Lorzen - 博客园

def drawInRectgle(img, cont, cX, cY, x_min, x_max, y_min, y_max):             """绘制不规则的内部直接矩形"""             # img 对应原图, 四个极值坐标对应四个最大的外矩形顶点             c = cont  # 单个轮廓             # print(c)             range_x, range_y = x_max - x_min, y_max - y_min   # 轮廓的X,Y的范围             x1, x2, y1, y2 = cX, cX, cY, cY     # 中心扩散矩形的四个顶点x,y             cnt_range, radio = 0, 0             shape_flag = 1                      # 1:轮廓X轴比Y长;0:轮廓Y轴比X长;             if range_x > range_y:                     # 判断轮廓 X方向更长                 radio, shape_flag = int(range_x / range_y), 1                 range_x_left = cX - x_min                 range_x_right = x_max - cX                 if range_x_left >= range_x_right:   # 取轴范围较长for循环                     cnt_range = int(range_x_left)                 if range_x_left < range_x_right:                     cnt_range = int(range_x_right)             else:                                   # 判断轮廓 Y方向更长                 radio, shape_flag = int(range_y / range_x), 0                 range_y_top = cY - y_min                 range_y_bottom = y_max - cY                 if range_y_top >= range_y_bottom:   # 取轴范围较长for循环                     cnt_range = int(range_y_top)                 if range_y_top < range_y_bottom:                     cnt_range = int(range_y_bottom)             print("X radio Y: %d " % radio)             print("---------new drawing range: %d-------------------------------------" % cnt_range)             flag_x1, flag_x2, flag_y1, flag_y2 = False, False, False, False             radio = 5       # 暂设5,统一比例X:Y=5:1 因为会发现一些东西X:Y=4:1, 某些会出现X:Y=5:1             if shape_flag == 1:                 radio_x = radio - 1                 radio_y = 1             else:                 radio_x = 1                 radio_y = radio - 1             for ix in range(1, cnt_range, 1):      # X方向延伸,假设X:Y=3:1,延长步进值X:Y=3:1                 # 第二象限延伸                 if flag_y1 == False:                     y1 -= 1 * radio_y       # 假设X:Y=1:1,轮廓XY方向长度接近,可理解为延伸步进X:Y=1:1                     p_x1y1 = cv.pointPolygonTest(c, (x1, y1), False)                     p_x2y1 = cv.pointPolygonTest(c, (x2, y1), False)                     if p_x1y1 <= 0 or y1 <= y_min or p_x2y1 <= 0:  # 只在轮廓外进行y操作,说明y超出了范围                         for count in range(0, radio_y - 1, 1):    # 最长返回步进延伸                             y1  = 1     # y超出, 步进返回                             p_x1y1 = cv.pointPolygonTest(c, (x1, y1), False)                             if p_x1y1 <= 0 or y1 <= y_min or p_x2y1 <= 0:                                 pass                             else:                                 break                         # print("y1 = %d, P=%d" % (y1, p_x1y1))                         flag_y1 = True                  if flag_x1 == False:                     x1 -= 1 * radio_x                     p_x1y1 = cv.pointPolygonTest(c, (x1, y1), False)    # 满足第二象限的要求,像素在轮廓内                     p_x1y2 = v.pointPolygonTest(c, (x1, y2), False)    # 满足第三象限的要求,像素都在轮廓内
                    if p_x1y1 <= 0 or x1 <= x_min or p_x1y2 <= 0:       # 若X超出轮廓范围
                        # x1 += 1  # x超出, 返回原点
                        for count in range(0, radio_x-1, 1):       #
                            x1 += 1         # x超出, 步进返回
                            p_x1y1 = cv.pointPolygonTest(c, (x1, y1), False)  # 满足第二象限的要求,像素都在轮廓内
                            p_x1y2 = cv.pointPolygonTest(c, (x1, y2), False)  # 满足第三象限的要求,像素都在轮廓内
                            if p_x1y1 <= 0 or x1 <= x_min or p_x1y2 <= 0:
                                pass
                            else:
                                break
                        # print("x1 = %d, P=%d" % (x1, p_x1y1))
                        flag_x1 = True              # X轴像左延展达到轮廓边界,标志=True
                # 第三象限延展
                if flag_y2 == False:
                    y2 += 1 * radio_y
                    p_x1y2 = cv.pointPolygonTest(c, (x1, y2), False)
                    p_x2y2 = cv.pointPolygonTest(c, (x2, y2), False)
                    if p_x1y2 <= 0 or y2 >= y_max or p_x2y2 <= 0:  # 在轮廓外,只进行y运算,说明y超出范围
                        for count in range(0, radio_y - 1, 1):  # 最长返回步进延展
                            y2 -= 1     # y超出, 返回原点
                            p_x1y2 = cv.pointPolygonTest(c, (x1, y2), False)
                            if p_x1y2 <= 0 or y2 >= y_max or p_x2y2 <= 0:  # 在轮廓外,只进行y运算,说明y超出范围
                                pass
                            else:
                                break
                        # print("y2 = %d, P=%d" % (y2, p_x1y2))
                        flag_y2 = True              # Y轴像左延展达到轮廓边界,标志=True
                # 第一象限延展
                if flag_x2 == False:
                    x2 += 1 * radio_x
                    p_x2y1 = cv.pointPolygonTest(c, (x2, y1), False)    # 满足第一象限的要求,像素都在轮廓内
                    p_x2y2 = cv.pointPolygonTest(c, (x2, y2), False)    # 满足第四象限的要求,像素都在轮廓内
                    if p_x2y1 <= 0 or x2 >= x_max or p_x2y2 <= 0:
                        for count in range(0, radio_x - 1, 1):  # 最长返回步进延展
                            x2 -= 1     # x超出, 返回原点
                            p_x2y1 = cv.pointPolygonTest(c, (x2, y1), False)  # 满足第一象限的要求,像素都在轮廓内
                            p_x2y2 = cv.pointPolygonTest(c, (x2, y2), False)  # 满足第四象限的要求,像素都在轮廓内
                            if p_x2y1 <= 0 or x2 >= x_max or p_x2y2 <= 0:
                                pass
                            elif p_x2y2 > 0:
                                break
                        # print("x2 = %d, P=%d" % (x2, p_x2y1))
                        flag_x2 = True
                if flag_y1 and flag_x1 and flag_y2 and flag_x2:
                    print("(x1,y1)=(%d,%d)" % (x1, y1))
                    print("(x2,y2)=(%d,%d)" % (x2, y2))
                    break
            # cv.line(img, (x1,y1), (x2,y1), (255, 0, 0))
            cv.rectangle(img, (x1, y1), (x2, y2), (255, 255, 255), 1, 8)

            return x1, x2, y1, y2

c++版

OpenCVSharp 小练习 最大内接矩形_tfarcraw的博客-CSDN博客

​​​​​​opencv:求区域的内接矩形_cfqcfqcfqcfqcfq的博客-CSDN博客_opencv 内接矩形

#include
#include 
#include
 
using namespace cv;
using namespace std;
 
/**
* @brief expandEdge 扩展边界函数
* @param img:输入图像,单通道二值图,深度为8
* @param edge  边界数组,存放4条边界值
* @param edgeID 当前边界号
* @return 布尔值 确定当前边界是否可以扩展
*/
 
bool expandEdge(const Mat & img, int edge[], const int edgeID)
{
	//[1] --初始化参数
	int nc = img.cols;
	int nr = img.rows;
	switch (edgeID) {
	case 0:
		if (edge[0]>nr)
			return false;
		for (int i = edge[3]; i <= edge[1]; ++i)
		{
			if (img.at(edge[0], i) == 255)//遇见255像素表明碰到边缘线
				return false;
		}
		edge[0]++;
		return true;
		break;
	case 1:
		if (edge[1]>nc)
			return false;
		for (int i = edge[2]; i <= edge[0]; ++i)
		{
			if (img.at(i, edge[1]) == 255)//遇见255像素表明碰到边缘线
				return false;
		}
		edge[1]++;
		return true;
		break;
	case 2:
		if (edge[2]<0)
			return false;
		for (int i = edge[3]; i <= edge[1]; ++i)
		{
			if (img.at(edge[2], i) == 255)//遇见255像素表明碰到边缘线
				return false;
		}
		edge[2]--;
		return true;
		break;
	case 3:
		if (edge[3]<0)
			return false;
		for (int i = edge[2]; i <= edge[0]; ++i)
		{
			if (img.at(i, edge[3]) == 255)//遇见255像素表明碰到边缘线
				return false;
		}
		edge[3]--;
		return true;
		break;
	default:
		return false;
		break;
	}
 
}
 
/**
* @brief 求取连通区域内接矩
* @param img:输入图像,单通道二值图,深度为8
* @param center:最小外接矩的中心
* @return  最大内接矩形
* 基于中心扩展算法
*/
 
cv::Rect InSquare(Mat &img, const Point center)
{
	// --[1]参数检测
	if (img.empty() ||img.channels()>1|| img.depth()>8)
		return Rect();
	// --[2] 初始化变量
	int edge[4];
	edge[0] = center.y + 1;//top
	edge[1] = center.x + 1;//right
	edge[2] = center.y - 1;//bottom
	edge[3] = center.x - 1;//left
						   //[2]
						   // --[3]边界扩展(中心扩散法)
 
	bool EXPAND[4] = { 1,1,1,1 };//扩展标记位
	int n = 0;
	while (EXPAND[0] || EXPAND[1] || EXPAND[2] || EXPAND[3])
	{
		int edgeID = n % 4;
		EXPAND[edgeID] = expandEdge(img, edge, edgeID);
		n++;
	}
	//[3]
	//qDebug() << edge[0] << edge[1] << edge[2] << edge[3];
	Point tl = Point(edge[3], edge[0]);
	Point br = Point(edge[1], edge[2]);
	return Rect(tl, br);
}
 
 
 
 
int main()
{
 
	bool isExistence = false;
	float first_area = 0;
	/// 加载源图像
	Mat src;
	src = imread("cen.bmp", 1);
	//src = imread("C:\\Users\\Administrator\\Desktop\\测试图片\\xxx\\20190308152516.jpg",1);
	//src = imread("C:\\Users\\Administrator\\Desktop\\测试图片\\xx\\20190308151912.jpg",1);
	//src = imread("C:\\Users\\Administrator\\Desktop\\测试图像\\2\\BfImg17(x-247 y--91 z--666)-(492,280).jpg",1);
	cvtColor(src, src, CV_RGB2GRAY);
	threshold(src, src, 100, 255, THRESH_BINARY);
	Rect ccomp;
	Point center(src.cols / 2, src.rows / 2);
	//floodFill(src, center, Scalar(255, 255, 55), &ccomp, Scalar(20, 20, 20), Scalar(20, 20, 20));
	if (src.empty())
	{
		cout << "fali" << endl;
	}
	//resize(src, src, cv::Size(496, 460), cv::INTER_LINEAR);
	imshow("src", src);
	Rect rr = InSquare(src, center);
	rectangle(src, rr, Scalar(255), 1, 8);
	imshow("src2", src);
 
	waitKey(0);
	getchar();
	return 0;
}

原图和效果图:

锐单商城拥有海量元器件数据手册IC替代型号,打造电子元器件IC百科大全!

相关文章