iOS は Opencv を使用して画像を回転、ズームイン、切り抜き、90 度回転します (ソース コード付き)

最近のプロジェクトには、写真を回転してズームインするという特別な要件があり、写真のズームイン角度がトリミング フレームの対角領域をカバーする必要があるため、opencv を使用してトリミングする必要があります。具体的な実装効果は次のとおりです:
挿入されるビデオ

考え方は次のとおりです。

1. 画像の回転角度の関係から、拡大した画像の倍数を計算します。画像の例は次のとおりです。

ここに画像の説明を挿入
この写真は (https://blog.csdn.net/liushuo19920327/article/details/126172379#comments_24864918) で参照されています。

倍率を取得するコードは次のとおりです。

//通过旋转角度获取放大倍数,这里的角度都是弧度
- (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;
}

2 つは opencv を使用して画像をトリミングします

回転角度に従ってズーム率が計算され、表示されている画像の現在のズーム率、画像の元のサイズと画像の表示サイズの間のズーム率、および回転角度に従って、最終的なトリミングが行われます。元画像のピクセル単位サイズの面積を計算し(回転後領域)、最終的にopencvの透視変換行列に従って最終的な回転画像を取得します。トリミングコードは以下の通りです。計算プロセスについては、を参照してください。コード

+(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);
}

90 度回転した 3 組の画像

opencv を使って画像を 90 度回転する簡単な方法

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

4 組の画像が指定された領域に従って切り取られます

// 裁剪图片 像素点
// - 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);
}

ソース コードのダウンロード アドレスは次のとおりです:ソース コードのダウンロード

おすすめ

転載: blog.csdn.net/mumubumaopao/article/details/130817170