iOS uses Opencv to rotate, zoom in, crop and rotate images 90 degrees (with source code)

There is a special requirement in the recent project, which is to rotate and zoom in on the picture, and the zoomed-in angle of the picture is required to cover the diagonal area of ​​the cropping frame, and then use opencv to crop the picture. The specific implementation effect is as follows: Video to be
inserted

The idea is as follows:

1. According to the rotation angle relationship of the picture, calculate the multiple of the enlarged picture. The example of the picture is as follows:

insert image description here
The picture is referenced at (https://blog.csdn.net/liushuo19920327/article/details/126172379#comments_24864918)

The code to get the magnification is as follows:

//通过旋转角度获取放大倍数,这里的角度都是弧度
- (CGFloat)getZoomScaleByAngleValue:(CGFloat)angleValue {
    CGFloat θ = fabs(angleValue);
    //裁剪框的frame
    //判断一下图片宽高 宽/高 || 高/宽
    CGRect cropFrame = self.shadowV.frame;
    CGFloat θ1 = atanf(cropFrame.size.height/cropFrame.size.width);
    if(cropFrame.size.height > cropFrame.size.width){
        θ1 = atanf(cropFrame.size.width/cropFrame.size.height);
    }
    
    CGFloat scale = 1 / (cosf(θ) - sinf(θ)/tanf(θ+θ1));
    return scale;
}

Two use opencv to crop the picture

According to the rotation angle, the zoom factor is calculated, and according to the current zoom factor of the displayed image, the zoom ratio between the original size of the image and the display size of the image, and the rotation angle, the final cropping area in the pixel unit size of the original image is calculated (after rotation region), and finally obtain the final rotated image according to the perspective transformation matrix of opencv. The cropping code is as follows. For the calculation process, please refer to the code

+(UIImage*)clipImageWithImage:(UIImage*)inputImage clipRect:(CGRect)outRect angle:(CGFloat)angle{    Mat img;
    UIImageToMat(inputImage,img,true);
    
    Mat g_dstImage=Mat::zeros(img.size(),img.type());
    
    // 定义旋转矩形区域的中心点、宽度、高度和旋转角度
    Point2f center(outRect.origin.x + outRect.size.width/2, outRect.origin.y + outRect.size.height/2);
    
    float width = outRect.size.width;
    float height = outRect.size.height;
    angle = angle;
    
    // 计算旋转矩形的四个顶点坐标
    float radians = angle * CV_PI / 180.0;
    float cos_angle = cos(radians);
    float sin_angle = sin(radians);
    
    vector<Point2f> src_pts;
    src_pts.push_back(Point2f(-width / 2, -height / 2));
    src_pts.push_back(Point2f(width / 2, -height / 2));
    src_pts.push_back(Point2f(width / 2, height / 2));
    src_pts.push_back(Point2f(-width / 2, height / 2));
    for (int i = 0; i < 4; i++) {
        float x = src_pts[i].x * cos_angle - src_pts[i].y * sin_angle + center.x;
        float y = src_pts[i].x * sin_angle + src_pts[i].y * cos_angle + center.y;
        if (x < 0 || y < 0 || x >= img.cols || y >= img.rows) {
            std::cout << "vertex point out of range.";
            return nil;
        }
        src_pts[i] = Point2f(x, y);
    }
    
    // 定义裁剪后输出的图像大小
    int output_width = outRect.size.width;
    int output_height = outRect.size.height;
    
    // 定义目标图像的四个点
    vector<Point2f> dst_pts;
    dst_pts.push_back(Point2f(0, 0));
    dst_pts.push_back(Point2f(output_width - 1, 0));
    dst_pts.push_back(Point2f(output_width - 1, output_height - 1));
    dst_pts.push_back(Point2f(0, output_height - 1));
    
    // 计算透视变换矩阵
    Mat M = getPerspectiveTransform(src_pts, dst_pts);
    
    // 应用透视变换
    Mat output_img;
    warpPerspective(img, output_img, M, cvSize(output_width, output_height));
    
    return MatToUIImage(output_img);
}

Three pairs of images rotated 90 degrees

A small method that can easily use opencv to rotate the picture by 90 degrees

+(UIImage*)rotate90WithImage:(UIImage*)inputImage{
    
    Mat src =  [CVTools cvMatFromUIImage:inputImage];
    
    Mat temp,dst;
    transpose(src, temp);
    flip(temp,dst,1);
    return [CVTools UIImageFromCVMat:dst];
}

Four pairs of images are cropped according to a given area

// 裁剪图片 像素点
// - Parameters:
//   - inputImage: 原图片
//   - outRect: 裁剪区域
+(UIImage*)clipImageWithImage:(UIImage*)inputImage clipRect:(CGRect)outRect{
    Mat img;
    UIImageToMat(inputImage,img,true);
    
    Mat cropped_image = img(Range(outRect.origin.y,outRect.size.height + outRect.origin.y), Range(outRect.origin.x,outRect.size.width + outRect.origin.x));
    
    return MatToUIImage(cropped_image);
}

The source code download address is here: Source code download

Guess you like

Origin blog.csdn.net/mumubumaopao/article/details/130817170