gpt4 book ai didi

android - OpenCV warp透视旋转不一致

转载 作者:行者123 更新时间:2023-12-02 17:38:20 27 4
gpt4 key购买 nike

找到最大轮廓(在本例中为优惠券)后,应用warpPerspective会导致不一致的变形,变形后它会向左旋转一些图像,但对于某些输入帧效果很好。

完美包裹的输入图像

INPUT PERFECT WARPING

输出完美包裹

OUTPUT PERFECT WARPING

输入要压缩的图像的图像

INPUT MESSED-UP WARPING

输出补足
enter image description here

    private Mat processMatToFindLargestContourAndApplyWarp(Mat srcMat) {
Mat processedMat = new Mat();
Imgproc.cvtColor(srcMat, processedMat, Imgproc.COLOR_BGR2GRAY);
Imgproc.GaussianBlur(processedMat, processedMat, new Size(5, 5), 5);
Imgproc.threshold(processedMat, processedMat, 127, 255, Imgproc.THRESH_BINARY);
List<MatOfPoint> contours = new ArrayList<>();

Imgproc.findContours(processedMat, contours, new Mat(), Imgproc.RETR_LIST, Imgproc.CHAIN_APPROX_NONE);

double maxVal = 0;
int maxValIdx = 0;
for (int contourIdx = 0; contourIdx < contours.size(); contourIdx++) {
double contourArea = Imgproc.contourArea(contours.get(contourIdx));
if (maxVal < contourArea) {
maxVal = contourArea;
maxValIdx = contourIdx;
}
}

if (!contours.isEmpty()) {
Imgproc.drawContours(processedMat, contours, maxValIdx, new Scalar(0, 255, 0), 3);
return warp(srcMat, contours.get(maxValIdx));
} else {
Toast.makeText(this, "Error: Token contour not found", Toast.LENGTH_LONG).show();
}
return srcMat;
}

public Mat warp(Mat inputMat, MatOfPoint selectedContour) {
Mat outputMat;
try {
MatOfPoint2f new_mat = new MatOfPoint2f(selectedContour.toArray());
MatOfPoint2f approxCurve_temp = new MatOfPoint2f();
int contourSize = (int) selectedContour.total();
Imgproc.approxPolyDP(new_mat, approxCurve_temp, contourSize * 0.05, true);

double[] temp_double;
temp_double = approxCurve_temp.get(0,0);
Point p1 = new Point(temp_double[0], temp_double[1]);
temp_double = approxCurve_temp.get(1,0);
Point p3 = new Point(temp_double[0], temp_double[1]);
temp_double = approxCurve_temp.get(2,0);
Point p4 = new Point(temp_double[0], temp_double[1]);
temp_double = approxCurve_temp.get(3,0);
Point p2 = new Point(temp_double[0], temp_double[1]);
List<Point> source = new ArrayList<Point>();

source.add(p1);
source.add(p2);
source.add(p3);
source.add(p4);

Log.e("inPoints", "" + source);
Mat startM = Converters.vector_Point2f_to_Mat(source);

int resultWidth = 846;
int resultHeight = 2048;

outputMat = new Mat(resultWidth, resultHeight, CvType.CV_8UC4);

Point ocvPOut1 = new Point(0, 0);
Point ocvPOut2 = new Point(resultWidth, 0);
Point ocvPOut3 = new Point(0, resultHeight);
Point ocvPOut4 = new Point(resultWidth, resultHeight);
List<Point> dest = new ArrayList<Point>();
dest.add(ocvPOut1);
dest.add(ocvPOut2);
dest.add(ocvPOut3);
dest.add(ocvPOut4);
Mat endM = Converters.vector_Point2f_to_Mat(dest);

Mat perspectiveTransform = Imgproc.getPerspectiveTransform(startM, endM);
Imgproc.warpPerspective(inputMat, outputMat, perspectiveTransform, new Size(resultWidth, resultHeight));
} catch (Exception e) {
return null;
}
return outputMat;
}

我尝试过切换边缘点,但是它适用于第二张图片,而不适用于第一张图片。我是否必须检查一下并按顺序排列要点,如果是这样,有人可以指导我如何进行操作,还是有更好的方法来处理此问题?

在我的日志结果中,由Imgproc.approxPolyDP收集的输入源点即使在有微小 Angular 情况下,对于具有优惠券的不同图像的排列也不一致。

最佳答案

我已经设法解决了这种情况,我敢肯定会有更好的方法来解决此问题,但目前为止,解决方法是手动将轮廓点按顺时针方向排序(即TopLeft,TopRight,BottomRight, BottomLeft)每次,无论输入点的排列如何。

如果有人被我困住,这是代码

    private Point[] orderCorners(Point[] cornersUnordered) {
Point[] cornerPoints = new Point[4];
Point p1, p2, p3, p4;
Point topLeft = null, topRight = null, botRight = null, botLeft = null;
List<Point> corners = new ArrayList<Point>();
for (int i=0; i < cornersUnordered.length; ++i)
corners.add(cornersUnordered[i]);

/* Top set of points */
// find p1
p1 = corners.get(0);
for (Point point : corners) {
if (point.y < p1.y) {
p1 = point;
}
}
corners.remove(p1);

// find p2
p2 = corners.get(0);
for (Point point : corners) {
if (distance(p1, point) < distance(p1, p2)) {
p2 = point;
}
}
corners.remove(p2);

/* Identify top left and top right */
/*
* Note that the logic is safe if the points have equal x values. Safe
* in the sense that different points will get assigned to topLeft and
* topRight
*/
topLeft = p1.x < p2.x ? p1 : p2;
topRight = p2.x > p1.x ? p2 : p1;

/* Bottom set of points */
// corners only contains 2 points, the bottom ones
p3 = corners.get(0);
p4 = corners.get(1);
botRight = p3.x > p4.x ? p3 : p4;
botLeft = p4.x < p3.x ? p4 : p3;

cornerPoints[0] = topLeft;
cornerPoints[1] = topRight;
cornerPoints[2] = botRight;
cornerPoints[3] = botLeft;

return cornerPoints;
}

private double distance(Point p1, Point p2) {
return Math.sqrt(Math.pow((p2.x - p1.x), 2) + Math.pow((p2.y - p1.y), 2));
}

这是上述修复程序的destinationPoints安排:
        Point ocvPOut1 = new Point(0, 0);
Point ocvPOut2 = new Point(resultWidth, 0);
Point ocvPOut3 = new Point(resultWidth, resultHeight);
Point ocvPOut4 = new Point(0, resultHeight);

特别感谢@Alexander Reynolds

关于android - OpenCV warp透视旋转不一致,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47743496/

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