gpt4 book ai didi

python - 如何在不包含(或少量)背景像素的情况下调整对象内的矩形或调整其大小?

转载 作者:太空狗 更新时间:2023-10-30 02:10:01 24 4
gpt4 key购买 nike

在应用阈值并找到对象的轮廓后,我使用以下代码获取对象周围的直矩形(或输入其指令的旋转矩形):

img = cv2.imread('image.png')
imgray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ret,thresh = cv2.threshold(imgray,127,255,cv2.THRESH_BINARY)
# find contours
contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
cnt = contours[0]
# straight rectangle
x,y,w,h = cv2.boundingRect(cnt)
img= cv2.rectangle(img,(x,y),(x+w,y+h),(0,255,0),2)

看图

然后我使用以下代码计算了直矩形内的对象和背景像素的数量:

# rectangle area (total number of object and background pixels inside the rectangle)
area_rect = w*h
# white or object pixels (inside the rectangle)
obj = cv2.countNonZero(imgray)
# background pixels (inside the rectangle)
bac = area_rect - obj

现在我想根据背景像素和对象像素之间的关系来调整对象的矩形,例如,让一个矩形占据对象的大部分,而没有或只有更少的背景像素:

我如何创建它?

最佳答案

这个问题可以表述为找到非凸多边形内接的最大矩形

近似解可以在这个 link 找到.

这个问题也可以表述为:对于每个角度,找到矩阵中仅包含零的最大矩形,在此 SO question 中进行了探索.

我的解决方案基于 this回答。这将仅找到轴对齐的矩形,因此您可以轻松地将图像旋转给定角度并将此解决方案应用于每个角度。我的解决方案是 C++,但您可以轻松地将它移植到 Python,因为我主要使用 OpenCV 函数,或者调整上述答案中的解决方案以考虑轮换。

我们在这里:

#include <opencv2\opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;


// https://stackoverflow.com/a/30418912/5008845
Rect findMinRect(const Mat1b& src)
{
Mat1f W(src.rows, src.cols, float(0));
Mat1f H(src.rows, src.cols, float(0));

Rect maxRect(0,0,0,0);
float maxArea = 0.f;

for (int r = 0; r < src.rows; ++r)
{
for (int c = 0; c < src.cols; ++c)
{
if (src(r, c) == 0)
{
H(r, c) = 1.f + ((r>0) ? H(r-1, c) : 0);
W(r, c) = 1.f + ((c>0) ? W(r, c-1) : 0);
}

float minw = W(r,c);
for (int h = 0; h < H(r, c); ++h)
{
minw = min(minw, W(r-h, c));
float area = (h+1) * minw;
if (area > maxArea)
{
maxArea = area;
maxRect = Rect(Point(c - minw + 1, r - h), Point(c+1, r+1));
}
}
}
}

return maxRect;
}


RotatedRect largestRectInNonConvexPoly(const Mat1b& src)
{
// Create a matrix big enough to not lose points during rotation
vector<Point> ptz;
findNonZero(src, ptz);
Rect bbox = boundingRect(ptz);
int maxdim = max(bbox.width, bbox.height);
Mat1b work(2*maxdim, 2*maxdim, uchar(0));
src(bbox).copyTo(work(Rect(maxdim - bbox.width/2, maxdim - bbox.height / 2, bbox.width, bbox.height)));

// Store best data
Rect bestRect;
int bestAngle = 0;

// For each angle
for (int angle = 0; angle < 90; angle += 1)
{
cout << angle << endl;

// Rotate the image
Mat R = getRotationMatrix2D(Point(maxdim,maxdim), angle, 1);
Mat1b rotated;
warpAffine(work, rotated, R, work.size());

// Keep the crop with the polygon
vector<Point> pts;
findNonZero(rotated, pts);
Rect box = boundingRect(pts);
Mat1b crop = rotated(box).clone();

// Invert colors
crop = ~crop;

// Solve the problem: "Find largest rectangle containing only zeros in an binary matrix"
// https://stackoverflow.com/questions/2478447/find-largest-rectangle-containing-only-zeros-in-an-n%C3%97n-binary-matrix
Rect r = findMinRect(crop);

// If best, save result
if (r.area() > bestRect.area())
{
bestRect = r + box.tl(); // Correct the crop displacement
bestAngle = angle;
}
}

// Apply the inverse rotation
Mat Rinv = getRotationMatrix2D(Point(maxdim, maxdim), -bestAngle, 1);
vector<Point> rectPoints{bestRect.tl(), Point(bestRect.x + bestRect.width, bestRect.y), bestRect.br(), Point(bestRect.x, bestRect.y + bestRect.height)};
vector<Point> rotatedRectPoints;
transform(rectPoints, rotatedRectPoints, Rinv);

// Apply the reverse translations
for (int i = 0; i < rotatedRectPoints.size(); ++i)
{
rotatedRectPoints[i] += bbox.tl() - Point(maxdim - bbox.width / 2, maxdim - bbox.height / 2);
}

// Get the rotated rect
RotatedRect rrect = minAreaRect(rotatedRectPoints);

return rrect;
}



int main()
{
Mat1b img = imread("path_to_image", IMREAD_GRAYSCALE);

// Compute largest rect inside polygon
RotatedRect r = largestRectInNonConvexPoly(img);

// Show
Mat3b res;
cvtColor(img, res, COLOR_GRAY2BGR);

Point2f points[4];
r.points(points);

for (int i = 0; i < 4; ++i)
{
line(res, points[i], points[(i + 1) % 4], Scalar(0, 0, 255), 2);
}

imshow("Result", res);
waitKey();

return 0;
}

结果图片是:

enter image description here

注意

我想指出这段代码没有优化,所以它可能会表现得更好。有关近似解决方案,请参阅 here , 以及在那里报道的论文。

answer一个相关的问题让我朝着正确的方向前进。

关于python - 如何在不包含(或少量)背景像素的情况下调整对象内的矩形或调整其大小?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32674256/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com