IOS關於從照相機獲取圖片的問題,初步探究通過攝像頭實現顏色與形狀識別機制== – iPhone手機開發技術文章 iPhone軟體開發教學課程

ios通過攝像頭獲取特定數據

文字太小可通過command ‘+’調大字體,溫馨提示。

註釋:
由於最近項目需求,需要一個能夠實現對攝像頭圖片獲取其中部分內容的功能,類似於二維碼掃描。但是隻需要獲取特定位置的像素塊進行簡單計算即可,所以聽上去還是很簡單的,但是經過實踐,發現,現實似乎與想象中不一樣,由於攝像頭拍到的數據,采用的是QZ(也就是CG框架)進行繪制,所以涉及到坐標系與frame的坐標系不一致的問題。

1:嘗試直接拿到攝像頭數據,先輸出看下。
code:
代碼略。

總結:
直接使用攝像頭數據再用imageView的方式顯示出來的時刻,我們發現,數據是正確的==。所見即所得的方式。
需要註意的是:
當圖片是橫向拍攝的時刻,我們可以看到,相機會自動將圖片進行90度旋轉,也就是說,系統在你橫向拍攝的時刻,會自動將圖片旋轉90度,滿足你正常情況下的觀看。

所以:
我們使用imageView對拿到的數據進行展示的時刻,數據並沒有顛倒的現象。為瞭防止出現這個現象的原因是出於imageView的內部實現,我們使用CgimageRef的方式,再次驗證
從攝像頭拿到的數據真的和我們所看到的一樣嗎?

code:

CGImageRef oldImageRef=image.CGImage;

UIImage* newImage=[UIImage imageWithCGImage:oldImageRef];

註釋:

在這裡,我們隻是對拿到的Image對象,先轉換成瞭CGimage,再使用UIImage的方法得到新的Image對象。

結果:我們發現,得到的圖像果然就是旋轉90度的圖片,而不再是原圖瞭。

UIImage* newImage=[UIImage imageWithCGImage:oldImageRef scale:.1 orientation:UIImageOrientationRight];

使用上面的語句,可以將圖像旋轉90度變成我們需要的樣子。

思考:

這麼簡單的變化中,圖片會不會丟失數據?
———

NSData* data=UIImageJPEGRepresentation(image, 0);

NSLog(@”%lu”,(unsigned long)data.length);

還好,數據沒有丟失。既然數據沒有丟失,那麼我們應該可以獲取到其中特定的一塊數據得出,再顯示出來才對。

問題來瞭:
我們要獲取某一塊數據的內容,我們應該怎麼傳遞rect呢?因為我們默認的rect與CG的坐標系並不同。是否需要轉換呢?

1:我們先試一下,先把數據轉過來,再從裡面拿一部分.
code:

CGImageRef imageRef=image.CGImage;

CGImageRef newimage=CGImageCreateWithImageInRect(imageRef, rect);

結果發現:
拿到的數據還是傾斜瞭90度。也就是說,我們上面對數據這樣的轉換其實根本沒有起到作用,數據在底層存儲的方式就是使用CG的坐標系存儲的。

經過試驗發現,[UIImage imageWithCGImage:oldImageRef scale:.1 orientation:UIImageOrientationRight]中,對orientation的改變,不會對我們的實驗結果產生任何影響。
也就是說,這個方法,其實並沒有對底層的數據進行操作,而隻不過是在初始化新的UIImage的時刻,對底層像素的讀取,orientation不同,方向也不同而已。

思考:

因為,我們使用上面的方法,並沒有操作到底層的像素矩陣,也就是我,我們如果想要解決這個問題,有兩種方式,
1:將底層數據矩陣轉換成我們需要的對應坐標系的內容。
這也就是CTM轉換。
將Image對象內部數據進行轉換。
code:

- (UIImage *)image:(UIImage *)image rotation:(UIImageOrientation)orientation
{
    long double rotate = 0.0;
    CGRect rect;
    float translateX = 0;
    float translateY = 0;
    float scaleX = 1.0;
    float scaleY = 1.0;
    
    switch (orientation) {
        case UIImageOrientationLeft:
            rotate = M_PI_2;
            rect = CGRectMake(0, 0, image.size.height, image.size.width);
            translateX = 0;
            translateY = -rect.size.width;
            scaleY = rect.size.width/rect.size.height;
            scaleX = rect.size.height/rect.size.width;
            break;
        case UIImageOrientationRight:
            rotate = 3 * M_PI_2;
            rect = CGRectMake(0, 0, image.size.height, image.size.width);
            translateX = -rect.size.height;
            translateY = 0;
            scaleY = rect.size.width/rect.size.height;
            scaleX = rect.size.height/rect.size.width;
            break;
        case UIImageOrientationDown:
            rotate = M_PI;
            rect = CGRectMake(0, 0, image.size.width, image.size.height);
            translateX = -rect.size.width;
            translateY = -rect.size.height;
            break;
        default:
            rotate = 0.0;
            rect = CGRectMake(0, 0, image.size.width, image.size.height);
            translateX = 0;
            translateY = 0;
            break;
    }
    
    UIGraphicsBeginImageContext(rect.size);
    CGContextRef context = UIGraphicsGetCurrentContext();
    //做CTM變換
    CGContextTranslateCTM(context, 0.0, rect.size.height);
    CGContextScaleCTM(context, 1.0, -1.0);
    CGContextRotateCTM(context, rotate);
    CGContextTranslateCTM(context, translateX, translateY);
    
    CGContextScaleCTM(context, scaleX, scaleY);
    //繪制圖片
    CGContextDrawImage(context, CGRectMake(0, 0, rect.size.width, rect.size.height), image.CGImage);
    
    UIImage *newPic = UIGraphicsGetImageFromCurrentImageContext();
    
    return newPic;
}

結論:

這裡的解決方案,就是對底層像素矩陣進行裝換之後,在對裡面數據截取一部分。可以解決截取部分內容的問題。

——————-

2:解決方案二:就是對rect進行裝換,根據數據底層,進行rect的轉換。

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *