熱成像項目反色和實時錄制技術處理

反色實現(xiàn)過程

一、 實現(xiàn)過程

1、 獲取硬件設備實時返回的圖片

  • 通過獲取的圖片轉(zhuǎn)換成視頻顯示贤徒。
  • 視頻幀率硬件返回是25幀 硬件的分辯率為 192 * 256 默認的。通過返回拿到每一幀YUV圖片數(shù)據(jù) 然后轉(zhuǎn)換成為RGBA 格式的圖片胃惜。

重點泞莉,需要理解YUV和RGBA的區(qū)別哪雕,才能正確轉(zhuǎn)換船殉。

(1)yuv是一種圖片儲存格式,跟RGB格式類似斯嚎。yuv中利虫,y表示亮度,單獨只有y數(shù)據(jù)就可以形成一張圖片堡僻,只不過這張圖片是灰色的糠惫。u和v表示色差(u和v也被稱為:Cb-藍色差,Cr-紅色差)钉疫,

  • 為什么要yuv硼讽?
    有一定歷史原因,最早的電視信號牲阁,為了兼容黑白電視固阁,采用的就是yuv格式。
    一張yuv的圖像城菊,去掉uv备燃,只保留y,這張圖片就是黑白的凌唬。
    而且yuv可以通過拋棄色差來進行帶寬優(yōu)化并齐。
    比如yuv420格式圖像相比RGB來說,要節(jié)省一半的字節(jié)大小,拋棄相鄰的色差對于人眼來說况褪,差別不大撕贞。

一張yuv格式的圖像,占用字節(jié)數(shù)為 (width * height + (width * height) / 4 + (width * height) /4) = (width * height) * 3 / 2

一張RGB格式的圖像窝剖,占用字節(jié)數(shù)為(width * height) * 3

有興趣 可以了解一下 YU V存儲方式和格式麻掸、采樣方式、數(shù)據(jù)量計算赐纱、YUV裁剪

- RGB 三個字?分別代表了 紅(Red)脊奋、綠(Green)、藍(Blue)疙描,這三種顏?稱為 三原?诚隙,將它們以不同的?例相加,可以產(chǎn)?多種多樣的顏?起胰。

?張1280 * 720 ??的圖?久又,就代表著它有1280 * 720 個像素點。其中每?個像素點的顏?顯示都采?RGB 編碼?法效五,將RGB 分別取不同的值地消,就會展示不同的顏?。

RGB 轉(zhuǎn)YUV

RGB 到Y(jié)UV 的轉(zhuǎn)換畏妖,就是將圖像所有像素點的R脉执、G、B 分量轉(zhuǎn)換到Y(jié)戒劫、U半夷、V 分量。

    Y = 0.299 * R + 0.587 * G + 0.114 * B 

    U = -0.147 * R - 0.289 * G + 0.436 * B 

    V = 0.615 * R - 0.515 * G - 0.100 * B

    R = Y + 1.14 * V 

    G = Y - 0.39 * U - 0.58 * V 

    B = Y + 2.03 * U

1迅细、常規(guī)轉(zhuǎn)換標準:


image.png

2巫橄、BT.601 標準:(SD TV)


image.png

3、BT.709 標準:(HD TV)
image.png

YUV轉(zhuǎn)RGB

轉(zhuǎn)換有幾個標準
1茵典、常規(guī)轉(zhuǎn)換標準:


image.png

2湘换、BT.601 標準:(SD TV)


image.png

3、BT.709 標準:(HD TV)
image.png

2统阿、通過轉(zhuǎn)換成RGBA后 的同時 根據(jù)條件 改變指定的像素色值彩倚。得到RGBA相應的圖片數(shù)據(jù),在渲染顯示出來砂吞。

實時錄制技術處理

  • 說一下過程
    1署恍、拿到每一幀圖片數(shù)據(jù)后,需要轉(zhuǎn)換成視頻流數(shù)據(jù)
- (CVPixelBufferRef)pixelBufferFromCGImage:(CGImageRef)image size:(CGSize)size {
    
    NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
                           
                           [NSNumber numberWithBool:YES],kCVPixelBufferCGImageCompatibilityKey,
                           
                           [NSNumber numberWithBool:YES],kCVPixelBufferCGBitmapContextCompatibilityKey,nil];
    
    CVPixelBufferRef pxbuffer = NULL;
    
    CVReturn status = CVPixelBufferCreate(kCFAllocatorDefault,size.width,size.height,kCVPixelFormatType_32ARGB,(__bridge CFDictionaryRef) options,&pxbuffer);
    
    NSParameterAssert(status == kCVReturnSuccess && pxbuffer != NULL);
    
    CVPixelBufferLockBaseAddress(pxbuffer,0);
    
    void *pxdata = CVPixelBufferGetBaseAddress(pxbuffer);
    
    NSParameterAssert(pxdata !=NULL);
    
    CGColorSpaceRef rgbColorSpace=CGColorSpaceCreateDeviceRGB();
    
    //    當你調(diào)用這個函數(shù)的時候蜻直,Quartz創(chuàng)建一個位圖繪制環(huán)境盯质,也就是位圖上下文袁串。當你向上下文中繪制信息時,Quartz把你要繪制的信息作為位圖數(shù)據(jù)繪制到指定的內(nèi)存塊呼巷。一個新的位圖上下文的像素格式由三個參數(shù)決定:每個組件的位數(shù)囱修,顏色空間,alpha選項
    
    CGContextRef context = CGBitmapContextCreate(pxdata,size.width,size.height,8,4*size.width,rgbColorSpace,kCGImageAlphaPremultipliedFirst);
    
    NSParameterAssert(context);
    
    
    CGContextDrawImage(context,CGRectMake(0,0,CGImageGetWidth(image),CGImageGetHeight(image)), image);
    
    // 釋放色彩空間
    
    CGColorSpaceRelease(rgbColorSpace);
    
    // 釋放context
    
    CGContextRelease(context);
    
    // 解鎖pixel buffer
    
    CVPixelBufferUnlockBaseAddress(pxbuffer,0);
    
    return pxbuffer;
    
}

2王悍、首先創(chuàng)建好一個視頻文件破镰,設置好視頻的 分辯率,文件格式压储、幀率鲜漩、文件大小
重點:

 //mp4的格式設置 編碼格式 寬度 高度
    NSDictionary *videoSettings = [NSDictionary dictionaryWithObjectsAndKeys:AVVideoCodecTypeH264, AVVideoCodecKey,
                                   [NSNumber numberWithInt:size.width], AVVideoWidthKey,
                                   [NSNumber numberWithInt:size.height], AVVideoHeightKey, nil];
    
    AVAssetWriterInput *writerInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo outputSettings:videoSettings];
    
    NSDictionary *sourcePixelBufferAttributesDictionary = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:kCVPixelFormatType_32ARGB],kCVPixelBufferPixelFormatTypeKey,nil];
    //    AVAssetWriterInputPixelBufferAdaptor提供CVPixelBufferPool實例,
    //    可以使用分配像素緩沖區(qū)寫入輸出文件。使用提供的像素為緩沖池分配通常
    //    是更有效的比添加像素緩沖區(qū)分配使用一個單獨的池
    AVAssetWriterInputPixelBufferAdaptor *adaptor = [AVAssetWriterInputPixelBufferAdaptor assetWriterInputPixelBufferAdaptorWithAssetWriterInput:writerInput sourcePixelBufferAttributes:sourcePixelBufferAttributesDictionary];
    
    NSParameterAssert(writerInput);
    
    NSParameterAssert([videoWriter canAddInput:writerInput]);
    
    if([videoWriter canAddInput:writerInput]){
        
        NSLog(@"11111");
        
    }else{
        
        NSLog(@"22222");
        
    }

    [videoWriter addInput:writerInput];
    
    [videoWriter startWriting];
    [videoWriter startSessionAtSourceTime:kCMTimeZero];

2集惋、就是一幀一幀 往視頻文件中添加幀數(shù)據(jù)了

 dispatch_queue_t dispatchQueue = dispatch_queue_create("mediaInputQueue", NULL);
    int __block frame = 0;
    __weak typeof(self)weakSelf = self;
    //開始寫視頻幀
    [writerInput requestMediaDataWhenReadyOnQueue:dispatchQueue usingBlock:^{
        while ([writerInput isReadyForMoreMediaData]) {
            if (_end) { //結(jié)束標記
                [writerInput markAsFinished];
                if (videoWriter.status == AVAssetWriterStatusWriting) {
                    NSCondition *cond = [[NSCondition alloc]init];
                    [videoWriter finishWritingWithCompletionHandler:^{
                        [cond lock];
                        [cond signal];
                        [cond unlock];
                    }];
                    [cond wait];
                    [cond unlock];
                    if (weakSelf.videoUrl) {
                        weakSelf.videoUrl(weakSelf.theVideoPath);
                    }//保存視頻方法
                }
                break;
            }
            dispatch_semaphore_wait(_seam, DISPATCH_TIME_FOREVER);
            if (_imageBuffer) {
                //寫入視頻幀數(shù)據(jù)
                if (![adaptor appendPixelBuffer:_imageBuffer withPresentationTime:CMTimeMake(frame, 25)]) {
                    NSLog(@"success視頻數(shù)據(jù)寫入失敗");
                }else{
                    NSLog(@"success視頻數(shù)據(jù)寫入成功");
                    frame++;
                }
                NSLog(@"--------->寫入數(shù)據(jù)");
                //釋放buffer
                CVPixelBufferRelease(_imageBuffer);
                CVPixelBufferRelease(_imgBuffer);
                _imgBuffer = NULL;
                _imageBuffer = NULL;
            }
        }
    }];    

寫放幀數(shù)據(jù) 必須保證一幀一幀 寫入視頻文件中去孕似,所以我這里使用了加鎖 和信號量來進行控制

最重要的是 分辯率 和 碼率 的設置。必須要設置合適大小 不然對視頻效果有很大影響

分辨率是以橫向和縱向的像素數(shù)量來衡量的刮刑,表示平面圖像的精細程度喉祭。視頻精細程度并不只取決于視頻分辨率,還取決于屏幕分辨率雷绢。
碼率是數(shù)據(jù)傳輸時單位時間傳送的數(shù)據(jù)位數(shù)泛烙,單位千位每秒,通俗理解為取樣率翘紊,單位時間內(nèi)取樣率越大蔽氨,精度就越高,處理出來的文件就越接近原始 霞溪,一般計算:碼率(kbps)= 文件大蟹踔汀(kb)/ 時長(s)
下菜樣:當 1080P 的視頻在 720P 屏幕上播放時中捆,需要將圖像縮小鸯匹,縮小操作也叫下采樣。

“下采樣”的定義為:對于一個樣值序列泄伪,間隔幾個樣值取樣一次殴蓬,得到新序列。
對于一幅分辨率為 MxN 的圖像蟋滴,對其進行 s 倍下采樣染厅,即得到 (M/s)x(N/s) 分辨率的圖像(s 應為 M、N 的公約數(shù))津函,就是把原始圖像 sxs 窗口內(nèi)的圖像變成一個像素肖粮,這個像素點的值就是窗口內(nèi)所有像素的均值。
最佳體驗為屏幕與視頻分辨率相同且全屏播放尔苦,視頻分辨率過高的話屏幕沒有能力去呈現(xiàn)涩馆,視頻分辨率過低的話無法發(fā)揮屏幕的能力行施。

上采樣:當 720P 的視頻在 1080P 屏幕上播放時,需要將圖像放大魂那,放大操作也叫上采樣蛾号。

“上采樣”幾乎都是采用內(nèi)插值方法,即在原有圖像的像素點之間采用合適的插值算法插入新的元素涯雅,所以圖像放大也稱為圖像插值鲜结。

常見插值算法技術原理:
1)鄰插值算法:將四個像素(放大一倍)用原圖一個像素的顏色填充,較簡單易實現(xiàn)活逆,早期的時候應用比較普遍精刷,但會產(chǎn)生明顯的鋸齒邊緣和馬賽克現(xiàn)象;
2)雙線性插值法:是對鄰插值法的一種改進蔗候,先對兩水平方向進行一階線性插值贬养,再在垂直方向上進行一階線性插值。能有效地彌補鄰插值算法的不足琴庵,但還存在鋸齒現(xiàn)象并會導致一些不期望的細節(jié)柔化误算;
3)雙三次插值法:是對雙線性插值法的改進,它不僅考慮到周圍四個直接相鄰像素點灰度值的影響迷殿,還考慮到它們灰度值變化率的影響儿礼,使插值生成的像素灰度值延續(xù)原圖像灰度變化的連續(xù)性,從而使放大圖像濃淡變化自然平滑

視頻編碼

通過特定的壓縮技術庆寺,將某個視頻格式的文件轉(zhuǎn)換成另一種視頻格式
如:H264 :它是一種面向塊蚊夫,基于運動補償?shù)囊曨l編碼標準
1、可以在低碼率情況下提供高質(zhì)量的視頻圖像懦尝,相比 H.263 可節(jié)省 50% 的碼率
2知纷、H.264 可以根據(jù)不同的環(huán)境使用不同的傳輸和播放速率,并且提供了豐富的錯誤處理工具陵霉,可以很好的控制或消除丟包和誤碼琅轧。
3、H.264 性能的改進是以增加復雜性為代價而獲得的踊挠,H.264 編碼的計算復雜度大約相當于 H.263 的 3 倍乍桂,解碼復雜度大約相當于 H.263 的 2 倍。

H.264 協(xié)議中定義了三種幀效床,分別為 I 幀睹酌、P 幀以及 B 幀:

(1)I 幀:I幀即幀內(nèi)編碼幀、關鍵幀剩檀,可以理解為一幀畫面的完整保留憋沿,解碼時只需要本幀數(shù)據(jù)就可以完成,不需要參考其他畫面沪猴,數(shù)據(jù)量比較大辐啄;
(2)P 幀:P幀即前向預測編碼幀甥绿,記錄當前幀跟上一關鍵幀(或P幀)的差別,解碼時依賴之前緩存的畫面则披,疊加上本幀定義的差別共缕,才能生成最終畫面,數(shù)據(jù)量較 I 幀小很多士复;
(3)B 幀:B幀即雙向預測編碼幀图谷,記錄當前幀跟前后幀的差別,解碼時依賴前面的I幀(或P幀)和后面的P幀阱洪,數(shù)據(jù)量比I幀和P幀小很多便贵。

數(shù)據(jù)壓縮比大約為:I幀:P幀:B幀 = 7:20:50,可見 P 幀和 B 幀極大的節(jié)省了數(shù)據(jù)量冗荸,節(jié)省出來的空間可以用來多保存一些 I 幀承璃,以實現(xiàn)在相同碼率下,提供更好的畫質(zhì)蚌本。

音視頻直播 主要就是以下幾個步驟

image.png

音頻

音頻處理我們首要需要知道的參數(shù):

1盔粹、音調(diào):泛指聲音的頻率信息,人耳的主觀感受為聲音的低沉(低音)或者尖銳(高音)程癌。
2舷嗡、響度:聲音的強弱
3、采樣率:聲音信息在由模擬信號轉(zhuǎn)化為數(shù)字信號過程中的精確程度嵌莉,采樣率越高进萄,聲音信息保留的越多。
4锐峭、采樣精度:聲音信息在由模擬信號轉(zhuǎn)化為數(shù)字信號過程中中鼠,表示每一個采樣點所需要的字節(jié)數(shù),一般為16bit(雙字節(jié))表示一個采樣點沿癞。
5援雇、聲道數(shù):相關的幾路聲音數(shù)量,常見的如單聲道抛寝、雙聲道熊杨、5.1聲道
6曙旭、音頻幀長:音頻處理或者壓縮所操作的一段音頻信息盗舰,常見的是10ms,20ms桂躏,30ms钻趋。

音頻常見的幾個問題處理
1、噪聲抑制:手機等設備采集的原始聲音往往包含了背景噪聲剂习,影響聽眾的主觀體驗蛮位,降低音頻壓縮效率较沪,可以適當解決這樣的問題。
2失仁、回聲消除:在視頻或者音頻通話過程中尸曼,本地的聲音傳輸?shù)綄Χ瞬シ胖螅曇魰粚Χ说柠溈孙L采集萄焦,混合著對端人聲一起傳輸?shù)奖镜夭シ趴亟危@樣本地播放的聲音包含了本地原來采集的聲音,造成主觀感覺聽到了自己的回聲拂封。
3茬射、自動增益控制:手機等設備采集的音頻數(shù)據(jù)往往有時候響度偏高,有時候響度偏低冒签,造成聲音忽大忽小在抛,影響聽眾的主觀感受。自動增益控制算法根據(jù)預先配置的參數(shù)對輸入聲音進行正向/負向調(diào)節(jié)萧恕,使得輸出的聲音適宜人耳的主觀感受刚梭。
4:靜音檢測:靜音檢測的基本原理:計算音頻的功率譜密度,如果功率譜密度小于閾值則認為是靜音票唆,否則認為是聲音望浩。靜音檢測廣泛應用于音頻編碼、AGC惰说、AECM等磨德。
5:舒適噪聲產(chǎn)生:舒適噪聲產(chǎn)生的基本原理:根據(jù)噪聲的功率譜密度,人為構(gòu)造噪聲吆视。廣泛適用于音頻編解碼器典挑。在編碼端計算靜音時的白噪聲功率譜密度,將靜音時段和功率譜密度信息編碼啦吧。在解碼端您觉,根據(jù)時間信息和功率譜密度信息,重建隨機白噪聲授滓。
它的應用場景:完全靜音時琳水,為了創(chuàng)造舒適的通話體驗,在音頻后處理階段添加隨機白噪聲般堆。

一般我比較喜歡使用VideoToolbox 進行視頻數(shù)據(jù)處理

在iOS平臺上對視頻數(shù)據(jù)進行H.264編碼有兩種方式:

軟件編碼:用ffmpeg等開源庫進行編碼在孝,他是用cpu進行相關計算的,效率比較低淮摔,但是比較通用私沮,是跨平臺的。
硬件編碼:用VideoToolbox今天編碼和橙,他是用GPU進行相關計算的仔燕,效率很高造垛。
在熟悉H.264的過程中,為更好的了解H.264晰搀,嘗試用VideoToolbox硬編碼與硬解碼H.264的原始碼流五辽。
今天我們主要來看看使用VideoToolbox硬編碼H.264。

用VideoToolbox硬編碼H.264步驟如下:

1.初始化攝像頭外恕,output設定的時候奔脐,需要設置delegate和輸出隊列。在delegate方法吁讨,處理采集好的圖像髓迎。

2.初始化VideoToolbox,設置各種屬性建丧。

3.獲取每一幀數(shù)并編碼排龄。

4.每一幀數(shù)據(jù)編碼完成后,在回調(diào)方法中判斷是不是關鍵幀翎朱,如果是關鍵幀需要用CMSampleBufferGetFormatDescription獲取CMFormatDescriptionRef橄维,然后用
CMVideoFormatDescriptionGetH264ParameterSetAtIndex取得PPS和SPS;最后把每一幀的所有NALU數(shù)據(jù)前四個字節(jié)變成0x00 00 00 01之后再寫入文件拴曲。

5.循環(huán)步驟3步驟4争舞。

6.調(diào)用VTCompressionSessionCompleteFrames完成編碼,然后銷毀session:VTCompressionSessionInvalidate澈灼,釋放session竞川。


image.png
image.png

事實上,使用 VideoToolbox 硬編碼的用途大多是推流編碼后的 NAL Unit 而不是寫入到本地一個 H.264 文件// 如果你想保存到本地叁熔,使用 AVAssetWriter 是一個更好的選擇委乌,它內(nèi)部也是會硬編碼的。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末荣回,一起剝皮案震驚了整個濱河市遭贸,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌心软,老刑警劉巖壕吹,帶你破解...
    沈念sama閱讀 217,185評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異删铃,居然都是意外死亡耳贬,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評論 3 393
  • 文/潘曉璐 我一進店門泳姐,熙熙樓的掌柜王于貴愁眉苦臉地迎上來效拭,“玉大人,你說我怎么就攤上這事胖秒《谢迹” “怎么了?”我有些...
    開封第一講書人閱讀 163,524評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我茫叭,道長镣煮,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,339評論 1 293
  • 正文 為了忘掉前任恃锉,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘眼刃。我一直安慰自己,他們只是感情好摇肌,可當我...
    茶點故事閱讀 67,387評論 6 391
  • 文/花漫 我一把揭開白布擂红。 她就那樣靜靜地躺著,像睡著了一般围小。 火紅的嫁衣襯著肌膚如雪昵骤。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,287評論 1 301
  • 那天肯适,我揣著相機與錄音变秦,去河邊找鬼。 笑死框舔,一個胖子當著我的面吹牛蹦玫,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播刘绣,決...
    沈念sama閱讀 40,130評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼钳垮,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了额港?” 一聲冷哼從身側(cè)響起饺窿,我...
    開封第一講書人閱讀 38,985評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎移斩,沒想到半個月后肚医,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,420評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡向瓷,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,617評論 3 334
  • 正文 我和宋清朗相戀三年肠套,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片猖任。...
    茶點故事閱讀 39,779評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡你稚,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情刁赖,我是刑警寧澤搁痛,帶...
    沈念sama閱讀 35,477評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站宇弛,受9級特大地震影響鸡典,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜枪芒,卻給世界環(huán)境...
    茶點故事閱讀 41,088評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望舅踪。 院中可真熱鬧纽甘,春花似錦、人聲如沸抽碌。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,716評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽咬展。三九已至泽裳,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間破婆,已是汗流浹背涮总。 一陣腳步聲響...
    開封第一講書人閱讀 32,857評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留祷舀,地道東北人瀑梗。 一個月前我還...
    沈念sama閱讀 47,876評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像裳扯,于是被迫代替她去往敵國和親抛丽。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,700評論 2 354

推薦閱讀更多精彩內(nèi)容