iOS使用Opencv對(duì)圖片進(jìn)行旋轉(zhuǎn)放大裁剪及90度旋轉(zhuǎn)(附源碼)

近期項(xiàng)目里有一個(gè)特殊的需求,對(duì)圖片進(jìn)行旋轉(zhuǎn)放大,并且要求圖片放大的角度正好覆蓋裁剪框?qū)蔷€的區(qū)域,然后使用opencv對(duì)圖片進(jìn)行裁剪,具體實(shí)現(xiàn)效果如下:
待插入視頻

思路如下:

一 根據(jù)圖片的旋轉(zhuǎn)角度關(guān)系,計(jì)算出放大圖片的倍數(shù),圖片實(shí)例如下:

ffdd94d3ce784373abe0a88c1b932222.png

圖片引用于(https://blog.csdn.net/liushuo19920327/article/details/126172379#comments_24864918

獲取放大倍數(shù)代碼如下:

//通過旋轉(zhuǎn)角度獲取放大倍數(shù),這里的角度都是弧度
- (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;
}

二 使用opencv對(duì)圖片進(jìn)行裁剪

根據(jù)旋轉(zhuǎn)角度,計(jì)算出縮放倍數(shù),根據(jù)顯示的image當(dāng)前的縮放倍數(shù),以及圖片原尺寸和圖片顯示尺寸的縮放比例,以及旋轉(zhuǎn)角度,計(jì)算得出最終在原圖像素單位尺寸上的裁剪區(qū)域(旋轉(zhuǎn)后的區(qū)域),最終根據(jù)opencv的透視變換矩陣,獲取到最終的旋轉(zhuǎn)后的圖片,裁剪代碼如下,計(jì)算過程的思路請(qǐng)參照代碼

+(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());
    
    // 定義旋轉(zhuǎn)矩形區(qū)域的中心點(diǎn)、寬度、高度和旋轉(zhuǎn)角度
    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;
    
    // 計(jì)算旋轉(zhuǎn)矩形的四個(gè)頂點(diǎn)坐標(biāo)
    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;
    
    // 定義目標(biāo)圖像的四個(gè)點(diǎn)
    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));
    
    // 計(jì)算透視變換矩陣
    Mat M = getPerspectiveTransform(src_pts, dst_pts);
    
    // 應(yīng)用透視變換
    Mat output_img;
    warpPerspective(img, output_img, M, cvSize(output_width, output_height));
    
    return MatToUIImage(output_img);
}

三 對(duì)圖片進(jìn)行90度旋轉(zhuǎn)

一個(gè)小方法,可以方便的使用opencv對(duì)圖片進(jìn)行90度旋轉(zhuǎn)

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

四 對(duì)圖片根據(jù)給定區(qū)域進(jìn)行裁剪

// 裁剪圖片 像素點(diǎn)
// - Parameters:
//   - inputImage: 原圖片
//   - outRect: 裁剪區(qū)域
+(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);
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容