rect = cv2.minAreaRect(c) box = cv2.boxPoints(rect) if imutils.is_cv2() else cv2.boxPoints(rect)
时间: 2024-05-22 12:17:15 浏览: 150
这是一个用于计算轮廓的最小可旋转矩形边界框以及其四个角(点)的代码段。其中,cv2.minAreaRect()函数用于对当前轮廓进行最小可旋转矩形边界框的计算,返回值rect为最小可旋转矩形边界框的信息,包括中心点、长宽、旋转角度等;cv2.boxPoints()函数则用于根据最小可旋转矩形的信息计算其四个角(点)的坐标,返回值box为由四个点坐标组成的numpy数组。imutils.is_cv2()的判断是为了兼容OpenCV2和OpenCV3两个版本。
相关问题
opencv python 图像处理 使用高斯滤波+cv2.adaptiveThreshold+canny算法 进行轮廓提取得到contours 在contours提取出面积不小于一定阈值threshold_area且两边接近平行于x轴、两边接近平行于y轴的矩形轮廓contour_rec 同时进行霍夫变化cv2.HoughLinesP得到直线lines 遍历lines 得到x1, y1, x2, y2 ,然后计算直线的斜率:slope = abs((y2 - y1) / (x2 - x1 + 0.001)) # 防止分母为0 通过直线的斜率筛选出相对水平与相对垂直的线:if slope > 5.5 or slope<0.17: # 如果斜率大于5.5,则认为是垂直线段 用筛选出相对水平与相对垂直的线去与对比矩形轮廓 若直线大部分与轮廓贴合 则画出该轮廓 能帮我用代码示例嘛
当然可以,以下是代码示例:
```
import cv2
import numpy as np
# 读取图像
img = cv2.imread('test.jpg')
# 灰度化
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 高斯滤波
blur = cv2.GaussianBlur(gray, (5, 5), 0)
# 自适应阈值化
th = cv2.adaptiveThreshold(blur, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY_INV, 11, 2)
# Canny边缘检测
edges = cv2.Canny(th, 30, 150)
# 轮廓提取
contours, hierarchy = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# 遍历轮廓
for contour in contours:
# 计算轮廓面积
area = cv2.contourArea(contour)
# 过滤面积小于阈值的轮廓
if area < threshold_area:
continue
# 计算轮廓外接矩形
rect = cv2.minAreaRect(contour)
box = cv2.boxPoints(rect)
box = np.int0(box)
# 计算外接矩形的长宽
width = rect[1][0]
height = rect[1][1]
# 过滤长宽比例不合适的矩形
if width / height > 5 or height / width > 5:
continue
# 霍夫变换检测直线
lines = cv2.HoughLinesP(edges, 1, np.pi / 180, 50, minLineLength=50, maxLineGap=10)
# 遍历直线
for line in lines:
x1, y1, x2, y2 = line[0]
# 计算直线斜率
slope = abs((y2 - y1) / (x2 - x1 + 0.001))
# 过滤斜率不合适的直线
if slope > 5.5 or slope < 0.17:
continue
# 判断直线是否与矩形贴合
if abs(y2 - y1) > abs(x2 - x1):
# 直线接近水平,判断是否与矩形上下两条边贴合
if abs(y1 - box[0][1]) < 10 or abs(y1 - box[1][1]) < 10:
# 绘制矩形
cv2.drawContours(img, [box], 0, (0, 0, 255), 2)
break
else:
# 直线接近垂直,判断是否与矩形左右两条边贴合
if abs(x1 - box[0][0]) < 10 or abs(x1 - box[1][0]) < 10:
# 绘制矩形
cv2.drawContours(img, [box], 0, (0, 0, 255), 2)
break
# 显示结果
cv2.imshow('result', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
```
这段代码中需要自己定义阈值`threshold_area`,表示过滤掉面积小于该值的轮廓。
python中cv2.camshift源代码
cv2.camshift() 是 OpenCV 中用于实现 CAMShift 算法的函数,其源代码可以在 OpenCV 的 GitHub 库中找到。
以下是 cv2.camshift() 的源代码:
```
CV_IMPL int cvCamShift( CvArr* imgProb, CvRect _window, CvTermCriteria criteria,
CvConnectedComp* _comp, CvBox2D* box )
{
const int TOLERANCE = 10;
int k, row, col, pix, iter;
int max_iter = criteria.max_iter;
float hsize[] = {0.25f, 0.25f, 0.5f, 0.5f, 0.75f, 1.f, 1.f, 1.f};
float hranges[] = {-180, 180};
float vmin = 0, vmax = 180, smin = 0;
float hist_thresh;
CvSize sz;
IplImage stub, *prob = (IplImage*)imgProb, *mask = 0;
uchar *mask_row = 0;
int mask_step = 0;
CvHistogram* hist = 0;
CvMoments m;
CvPoint2D32f center, old_center;
float a, b, c, xscale, yscale, max_val;
CvBox2D box0;
CV_FUNCNAME( "cvCamShift" );
__BEGIN__;
if( !CV_IS_IMAGE( prob ))
CV_ERROR( CV_StsBadArg, "The probability map is not a valid image" );
if( prob->depth != IPL_DEPTH_32F || prob->nChannels != 1 )
CV_ERROR( CV_StsUnsupportedFormat,
"Only 32-bit floating-point, single-channel probability images are supported" );
if( !CV_ARE_SIZES_EQ( prob, &_window ))
CV_ERROR( CV_StsUnmatchedSizes, "The probability map size differs from the tracking window size" );
if( criteria.type & CV_TERMCRIT_EPS )
criteria.epsilon *= criteria.epsilon;
else
criteria.epsilon = 0;
criteria.epsilon = MAX( criteria.epsilon, 1e-8f );
criteria.max_iter = MAX( criteria.max_iter, 1 );
if( criteria.type & CV_TERMCRIT_ITER )
criteria.max_iter = MIN( criteria.max_iter, 100 );
else
criteria.max_iter = 100;
// allocate images
sz = cvGetSize( prob );
mask = cvCreateImage( sz, IPL_DEPTH_8U, 1 );
cvRectangle( mask, cvPoint(0,0), cvPoint(sz.width,sz.height), CV_RGB(255,255,255), -1 );
cvSetImageROI( mask, _window );
cvSet( mask, cvScalar(0) );
cvResetImageROI( mask );
hist = cvCreateHist( 1, &hist_size, CV_HIST_ARRAY, &h_ranges, 1 );
cvCalcArrHist( &prob, hist, 0 );
cvGetMinMaxHistValue( hist, 0, &max_val, 0, 0 );
cvConvertScale( hist->bins, hist->bins, max_val? 255.0/max_val : 0, 0 );
// cam-shift iteration
center.x = (_window.x + _window.width - 1)*0.5f;
center.y = (_window.y + _window.height - 1)*0.5f;
old_center = center;
box0.center = center;
box0.size.width = _window.width;
box0.size.height = _window.height;
box0.angle = 0;
iter = 0;
for(;;)
{
CvBox2D box1;
float *row_ptr;
float m00, m10, m01;
if( center.x <= 0 || center.x >= sz.width-1 ||
center.y <= 0 || center.y >= sz.height-1 )
break;
cvSetImageROI( prob, _window );
cvSetImageROI( mask, _window );
cvCalcArrHist( &prob, hist, 0 );
cvGetMinMaxHistValue( hist, 0, &max_val, 0, 0 );
hist_thresh = max_val * (1.f - criteria.epsilon);
cvThreshHist( hist, hist_thresh );
cvNormalizeHist( hist, 1 );
// find the x and y gradients
assert( CV_MAT_DEPTH( prob->type ) == CV_32F );
cvSobel( prob, dx, 1, 0, 1 );
cvSobel( prob, dy, 0, 1, 1 );
// initialize the transition matrix H = J'J
m00 = m10 = m01 = 0;
row_ptr = (float*)(dx->imageData + dx->widthStep);
for( row = 1; row <= _window.height; row++, row_ptr += dx->widthStep )
for( col = 1; col <= _window.width; col++ )
{
pix = cvRound(row_ptr[col]);
m00 += pix*pix;
m10 += (float)col*pix;
m01 += (float)row*pix;
}
H[0] = m00; H[1] = m10; H[2] = m01;
H[3] = m10; H[4] = (float)_window.width*_window.width; H[5] = 0;
H[6] = m01; H[7] = 0; H[8] = (float)_window.height*_window.height;
// calculate the update step
cvSolve( &H, &dh, &dp, CV_LU );
if( fabs(dp.x) > (float)_window.width*TOLERANCE ||
fabs(dp.y) > (float)_window.height*TOLERANCE )
break;
// update the window position
center.x += dp.x;
center.y += dp.y;
_window.x = cvRound(center.x - _window.width*0.5f);
_window.y = cvRound(center.y - _window.height*0.5f);
if( iter >= max_iter )
break;
if( _window.x < 0 || _window.x + _window.width >= sz.width ||
_window.y < 0 || _window.y + _window.height >= sz.height )
break;
box1.center = center;
box1.size.width = _window.width;
box1.size.height = _window.height;
box1.angle = 0;
a = (float)fabs( box0.size.width - box1.size.width );
b = (float)fabs( box0.size.height - box1.size.height );
c = (float)fabs( box0.angle - box1.angle );
c = c >= 180 ? 360 - c : c;
if( a < _window.width*0.05f &&
b < _window.height*0.05f &&
c < 2.0f )
break;
box0 = box1;
iter++;
}
if( _comp )
{
memset( _comp, 0, sizeof(*_comp));
_comp->rect.x = _window.x;
_comp->rect.y = _window.y;
_comp->rect.width = _window.width;
_comp->rect.height = _window.height;
_comp->area = 0;
mask_row = (uchar*)(mask->imageData + mask->widthStep*(int)_window.y);
mask_step = mask->widthStep;
}
if( box )
{
box->center = center;
box->size.width = _window.width;
box->size.height = _window.height;
box->angle = 0;
}
if( _comp )
{
for( row = 0; row < _window.height; row++, mask_row += mask_step )
for( col = 0; col < _window.width; col++ )
if( mask_row[col] )
_comp->area++;
if( _comp->area > 0 )
{
_comp->value = -1;
_comp->rect.width--;
_comp->rect.height--;
cvCalcSubPixelMoment( &m, prob, ¢er );
_comp->centroid.x = m.m10/m.m00 + _window.x;
_comp->centroid.y = m.m01/m.m00 + _window.y;
}
}
__END__;
cvReleaseImage( &mask );
cvReleaseHist( &hist );
cvReleaseImage( &dx );
cvReleaseImage( &dy );
return cvGetErrStatus();
}
```
该函数的实现包括以下步骤:
1. 对输入的概率图像进行判断;
2. 分配内存;
3. 计算直方图;
4. CAMShift 迭代;
5. 返回结果。
在 CAMShift 迭代中,该函数会计算梯度,判断迭代是否终止,并更新窗口位置和大小。
阅读全文