public void transform(View view) {
//最开始的图片
Mat sampledImage = ImageUtils.bitmapToMat(mBitmap);
//变换后图片
Mat correctedImage = new Mat(sampledImage.rows(), sampledImage.cols(), sampledImage.type());
Map<Integer, PointF> points = mPolygonView.getPoints();
//屏幕选中点的坐标转换为图片坐标
List<Point> srccorners = getSrcPoint(mBitmap, points);
List<Point> descorners = new ArrayList<>();
descorners.add(new Point(0, 0));
descorners.add(new Point(correctedImage.cols(), 0));
descorners.add(new Point(0, correctedImage.rows()));
descorners.add(new Point(correctedImage.cols(), correctedImage.rows()));
Mat srcPoints = Converters.vector_Point2f_to_Mat(srccorners);
Mat desPoints = Converters.vector_Point2f_to_Mat(descorners);
//求出变换矩阵
Mat transformation = Imgproc.getPerspectiveTransform(srcPoints, desPoints);
//进行仿射变换
Imgproc.warpPerspective(sampledImage, correctedImage, transformation, correctedImage.size());
displayImage(correctedImage);
}
//ImageUtil的bitmapToMat()方法
public static Mat bitmapToMat(Bitmap bitmap) {
Mat mat = new Mat(bitmap.getHeight(), bitmap.getWidth(), CvType.CV_8U, new Scalar(4));
Bitmap bitmap32 = bitmap.copy(Bitmap.Config.ARGB_8888, true);
Utils.bitmapToMat(bitmap32, mat);
return mat;
}
//ImageUtil的matToBitmap()方法
public static Bitmap matToBitmap(Mat mat) {
Bitmap bitmap = Bitmap.createBitmap(mat.cols(), mat.rows(), Bitmap.Config.ARGB_8888);
Utils.matToBitmap(mat, bitmap);
return
//屏幕坐标与图片坐标转换
private List<Point> getSrcPoint(Bitmap original, Map<Integer, PointF> points) {
List<Point> srccorners = new ArrayList<>();
float xRatio = (float) original.getWidth() / mImageView.getWidth();
float yRatio = (float) original.getHeight() / mImageView.getHeight();
float x1 = (points.get(0).x) * xRatio;
float x2 = (points.get(1).x) * xRatio;
float x3 = (points.get(2).x) * xRatio;
float x4 = (points.get(3).x) * xRatio;
float y1 = (points.get(0).y) * yRatio;
float y2 = (points.get(1).y) * yRatio;
float y3 = (points.get(2).y) * yRatio;
float y4 = (points.get(3).y) * yRatio;
srccorners.add(new Point(x1, y1));
srccorners.add(new Point(x2, y2));
srccorners.add(new Point(x3, y3));
srccorners.add(new Point(x4, y4));
return
PolygonView
public class PolygonView extends FrameLayout {
private Context mContext;
private Paint mPaint;
private ImageView mPointer1;
private ImageView mPointer2;
private ImageView mPointer3;
private ImageView mPointer4;
private PolygonView mPolygonView;
public PolygonView(@NonNull Context context) {
this(context, null);
}
public PolygonView(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init(context);
}
private void init(Context context) {
mContext = context;
mPolygonView = this;
mPointer1 = getImageView(0, 0);
mPointer2 = getImageView(getWidth(), 0);
mPointer3 = getImageView(0, getHeight());
mPointer4 = getImageView(getWidth(), getHeight());
addView(mPointer1);
addView(mPointer2);
addView(mPointer3);
addView(mPointer4);
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setColor(getResources().getColor(R.color.blue));
mPaint.setStrokeWidth(2);
}
private ImageView getImageView(int x, int y) {
ImageView imageview = new ImageView(mContext);
LayoutParams layoutparams = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
imageview.setLayoutParams(layoutparams);
imageview.setImageResource(R.drawable.circle);
imageview.setX(x);
imageview.setY(y);
imageview.setOnTouchListener(new TouchListaner());
return imageview;
}
private class TouchListaner implements OnTouchListener {
PointF downPoint = new PointF();
PointF startPoint = new PointF();
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
downPoint.x = event.getX();
downPoint.y = event.getY();
startPoint = new PointF(v.getX(), v.getY());
break;
case MotionEvent.ACTION_MOVE:
PointF mv = new PointF(event.getX() - downPoint.x, event.getY() - downPoint.y);
if ((startPoint.x + mv.x + v.getWidth()) < mPolygonView.getWidth() &&
(startPoint.y + mv.y + v.getHeight()) < mPolygonView.getHeight() &&
(startPoint.x + mv.x) > 0 && (startPoint.y + mv.y) > 0
) {
v.setX(startPoint.x + mv.x);
v.setY(startPoint.y + mv.y);
startPoint = new PointF(v.getX(), v.getY());
}
break;
case MotionEvent.ACTION_UP:
int color = 0;
if (isValidShape(getPoints())) {
color = getResources().getColor(R.color.blue);
} else {
color = getResources().getColor(R.color.orange);
}
mPaint.setColor(color);
break;
}
mPolygonView.invalidate();
return true;
}
}
public Map<Integer, PointF> getPoints() {
List<PointF> points = new ArrayList<>();
points.add(new PointF(mPointer1.getX(), mPointer1.getY()));
points.add(new PointF(mPointer2.getX(), mPointer2.getY()));
points.add(new PointF(mPointer3.getX(), mPointer3.getY()));
points.add(new PointF(mPointer4.getX(), mPointer4.getY()));
return getOrderedPoints(points);
}
/**
* 为各个点重新排序
* @param points
* @return
*/
public Map<Integer,PointF> getOrderedPoints(List<PointF> points){
PointF centerPoint=new PointF();
int size=points.size();
for(PointF point:points){
centerPoint.x+=point.x/size;
centerPoint.y+=point.y/size;
}
Map<Integer,PointF> orderedPoints=new HashMap<>();
for (PointF point:points){
int index=-1;
if (point.x<centerPoint.x&&point.y<centerPoint.y){
index=0;
}else if (point.x>centerPoint.x&&point.y<centerPoint.y){
index=1;
}else if (point.x<centerPoint.x&& point.y>centerPoint.y){
index=2;
}else if (point.x>centerPoint.x&&point.y>centerPoint.y){
index=3;
}
orderedPoints.put(index,point);
}
return orderedPoints;
}
public boolean isValidShape(Map<Integer, PointF> pointFMap) {
return pointFMap.size() == 4;
}
@Override
protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
canvas.drawLine(mPointer1.getX() + (mPointer1.getWidth() / 2), mPointer1.getY() + (mPointer1.getHeight() / 2), mPointer3.getX() + (mPointer3.getWidth() / 2), mPointer3.getY() + (mPointer3.getHeight() / 2), mPaint);
canvas.drawLine(mPointer1.getX() + (mPointer1.getWidth() / 2), mPointer1.getY() + (mPointer1.getHeight() / 2), mPointer2.getX() + (mPointer2.getWidth() / 2), mPointer2.getY() + (mPointer2.getHeight() / 2), mPaint);
canvas.drawLine(mPointer2.getX() + (mPointer2.getWidth() / 2), mPointer2.getY() + (mPointer2.getHeight() / 2), mPointer4.getX() + (mPointer4.getWidth() / 2), mPointer4.getY() + (mPointer4.getHeight() / 2), mPaint);
canvas.drawLine(mPointer3.getX() + (mPointer3.getWidth() / 2), mPointer3.getY() + (mPointer3.getHeight() / 2), mPointer4.getX() + (mPointer4.getWidth() / 2), mPointer4.getY() + (mPointer4.getHeight() / 2), mPaint);
}
public void setPoints(Map<Integer, PointF> pointFMap) {
if (pointFMap.size() == 4) {
setPointsCoordinates(pointFMap);
}
}
private void setPointsCoordinates(Map<Integer, PointF> pointFMap) {
mPointer1.setX(pointFMap.get(0).x);
mPointer1.setY(pointFMap.get(0).y);
mPointer2.setX(pointFMap.get(1).x);
mPointer2.setY(pointFMap.get(1).y);
mPointer3.setX(pointFMap.get(2).x);
mPointer3.setY(pointFMap.get(2).y);
mPointer4.setX(pointFMap.get(3).x);
mPointer4.setY(pointFMap.get(3).y);