问题
I current have a ArrayList<MatOfPoint>
which stores the contours of the image and have retrieved the largest contour which is my target for the warpPerspective.
List<MatOfPoint> contours = new ArrayList<MatOfPoint>();
Imgproc.findContours(matOut, contours, new Mat(), Imgproc.RETR_LIST, Imgproc.CHAIN_APPROX_SIMPLE);
sort(contours);
MatOfPoint2f m2f = MatOfPoint2f(contours.get(0).toArray());
double arc = Imgproc.arcLength(m2f, true);
MatOfPoint2f approx = new MatOfPoint2f();
Imgproc.approxPolyDP(m2f, approx, arc*0.02, true);
I am having trouble on how to use the getPerspectiveTransform and then applying the warpPerspective to change the image so that it will fit within a 450x450 image.
I found an pretty good example of this in python, however I am not very familiar with it can someone explain how I would do rectify in java?
def rectify(h):
''' this function put vertices of square we got, in clockwise order '''
h = h.reshape((4,2))
hnew = np.zeros((4,2),dtype = np.float32)
add = h.sum(1)
hnew[0] = h[np.argmin(add)]
hnew[2] = h[np.argmax(add)]
diff = np.diff(h,axis = 1)
hnew[1] = h[np.argmin(diff)]
hnew[3] = h[np.argmax(diff)]
return hnew
here is the source link: https://github.com/abidrahmank/OpenCV2-Python/blob/master/OpenCV_Python_Blog/sudoku_v_0.0.6/sudoku.py
回答1:
Intro: to make use of wrapPerspective we need to calculate wrapping mat using getPerspectiveTransform takes: Mat src and Mat dst. Those are MarOfPoints2f with src(top-left, top-right, bottom-left, bottom-right) of your contour and corresponding mat dst( 0,0 ; 0,449 ; 449,0 ; 449,449) (So the image will be 450x450 - If this is wrong please correct me).
Solution in Java for opencv 3 would be:
Get points sorted Having rectangular contour as MatOfPoints2f approx we need to sort the points as written above:
//calculate the center of mass of our contour image using moments Moments moment = Imgproc.moments(approx.get(0)); int x = (int) (moment.get_m10() / moment.get_m00()); int y = (int) (moment.get_m01() / moment.get_m00()); //SORT POINTS RELATIVE TO CENTER OF MASS Point[] sortedPoints = new Point[4]; double[] data; int count = 0; for(int i=0; i<approx.get(0).rows(); i++){ data = approx.get(0).get(i, 0); double datax = data[0]; double datay = data[1]; if(datax < x && datay < y){ sortedPoints[0]=new Point(datax,datay); count++; }else if(datax > x && datay < y){ sortedPoints[1]=new Point(datax,datay); count++; }else if (datax < x && datay > y){ sortedPoints[2]=new Point(datax,datay); count++; }else if (datax > x && datay > y){ sortedPoints[3]=new Point(datax,datay); count++; } }
Prepare Mat src and det
MatOfPoint2f src = new MatOfPoint2f( sortedPoints[0], sortedPoints[1], sortedPoints[2], sortedPoints[3]); MatOfPoint2f dst = new MatOfPoint2f( new Point(0, 0), new Point(450-1,0), new Point(0,450-1), new Point(450-1,450-1) );
Use getPerspectiveTransform and wrapPrespective
Mat warpMat = Imgproc.getPerspectiveTransform(src,dst); //This is you new image as Mat Mat destImage = new Mat(); Imgproc.warpPerspective(originalImg, destImage, warpMat, originalImg.size());
I have just finished doing similar project so I am sure this can be done better but it is a working solution if anyone needs one.
来源:https://stackoverflow.com/questions/40688491/opencv-getperspectivetransform-and-warpperspective-java