顯示具有 Computer Vision 標籤的文章。 顯示所有文章
顯示具有 Computer Vision 標籤的文章。 顯示所有文章

2013年12月11日 星期三

OpenCL 模擬 iOS7 毛玻璃效果(frosted glass)

最近筆者將手機作業系統升級到 iOS7, 發現 iOS7 的介面有一個亮點 : 毛玻璃(frosted glass)效果, 透過毛玻璃所在的 layer, 可以隱約看到下層 layer 的內容. 如圖一所示.

圖一
搜尋一些資訊後發現 不少人在討論這個效果, 因為 apple 使用的方法無法確切得知, 所以筆者就以自己的想法實作.  首先 需要一個用以柔化影像的 low-pass filter. 筆者計畫使用 Gaussian filter 並且使用 GPU 做 Gaussian filter convolution. 關於 Gaussian filter, 可以參考下面兩個在 wiki 的介紹:
Gaussian kernel 的大小由 sigma 決定, Host 端的程式根據 sigma 決定 kernel size, 根據 gaussian filter 的定義計算 mask 中的每個常數, 將 mask 儲存在 OpenCL 的 image object.    kernel size 以及 mask 會給 OpenCL kernel 進行 convolution 時使用. 用以計算 Gaussian mask 的程式片段如下:

void
CreateBlurMask(float sigma, int * maskSizePointer) 
{
int maskSize = (int)ceil(3.0f*sigma);
g_mask.resize((maskSize*2+1)*(maskSize*2+1));

float sum = 0.0f;
float* pmask = &g_mask[0];
pmask += maskSize*(maskSize*2+1) + maskSize;

for(int a = -maskSize; a < maskSize+1; a++)
{
for(int b = -maskSize; b < maskSize+1; b++) 
{
float temp = exp(-((float)(a*a+b*b) / (2*sigma*sigma)));
sum += temp;
pmask[a+b*(maskSize*2+1)] = temp;
}
}
// Normalize the mask
for(int i = 0; i < (maskSize*2+1)*(maskSize*2+1); i++)
g_mask[i] = g_mask[i] / sum;

*maskSizePointer = maskSize;
}

根據我前一篇文章 OpenCL介紹 作修改, 在 host 端程式代碼的初始化, 大致上增加了以下的部分.
調用 CreateBlurMask, 並且給定 sigma = 3.0

CreateBlurMask(3.0, &g_maskSize);

接著, 建立一個 image object, 並且將 Gaussian mask 的內容由 host 端的 memory 複製到 device 端的 memory:
imgObject[2] = clCreateImage2D(GPU_context, CL_MEM_READ_ONLY,                                                                  &mask_fmt, g_maskSize*2+1, 
                                                       g_maskSize*2+1, 0, NULL, NULL);

err = clEnqueueWriteImage(commandQueue, imgObject[2], CL_TRUE, origin, 
                                         mask_region, 0, 0, &g_mask[0], 0, NULL, NULL);

if(err != CL_SUCCESS) 
{
cleanUpOpenCL(GPU_context, commandQueue, program, kernel, 
         memoryObjects, numberOfMemoryObjects,
 imgObject, numberOfImgObjects);
return 0;

}

設定好送進 kernel function 的參數
clSetKernelArg(kernel, 2, sizeof(cl_mem), &imgObject[2]);  // source image
clSetKernelArg(kernel, 3, sizeof(cl_int), &g_maskSize);       //  mask Size


Host 端處理每個 frame 的流程如下:
(1) 產生一份原始影像 scaling down 成較低解析度後的結果.
(2) 讓GPU對 較低解析度的影像 進行 convolution.
(3) 讀回結果.
(4) CPU 將讀回的結果scaling up 成和原始影像一樣解析度.
(5) CPU 根據 ROI,  將scaling up後的影像和原始影像合成.

圖二

因為要 composition, 故需要產生一份 composition 使用的 mask. 此mask 在 ROI 內的值為 0xff,其餘部分皆為 0.

camera >> Img1;
Mat mask(Img1.rows, Img1.cols, CV_8UC1);
mask.setTo(0);

Mat roi(mask, Rect(140,100,340,260));
roi = 0xff;

composition 的代碼如下, ocl_img 是從讀回讀回並 scaling up 的結果. Img0 則是原始影像.
ocl_img *= 0.3;
ocl_img.copyTo( Img0, mask );

接下來看 Kernel Function 的內容:
__constant sampler_t sampler = CLK_NORMALIZED_COORDS_FALSE |
                               CLK_ADDRESS_CLAMP | 
                               CLK_FILTER_NEAREST;

__kernel void laplacian( read_only  image2d_t src_image,                         
                         write_only image2d_t dst_image,
                         read_only  image2d_t mask,
                         __private int maskSize )
{
int x = get_global_id(0);
int y = get_global_id(1);

int2 pos = {get_global_id(0), get_global_id(1)};


    // Collect neighbor values and multiply with Gaussian
    float4 fSum  = 0.0f;
    float4 fMask;
    
    float4 fColor;
    uint4  uiColor;    
    
    for(int a = -maskSize; a < maskSize+1; a++) 
    {
        for(int b = -maskSize; b < maskSize+1; b++) 
        {
            int2 coord = (int2)((a+maskSize, b+maskSize));
            uiColor = read_imageui(src_image, sampler, pos + (int2)(a,b));
            fColor  = convert_float4(uiColor);
            
            fMask   = read_imagef(mask, sampler, coord);
            
            fSum += fColor * fMask.x;
        }
    }
       
    uiColor = convert_uint4 (fSum);   
    write_imageui(dst_image, pos, uiColor);    
}
Kernel 這邊的代碼 根據 mask size 進行 convolution, 再將結果寫到 output image object.

2013年1月29日 星期二

攝像頭校正 camera calibration - part3 OpenCV programming

攝像頭校正 camera calibration - part3 OpenCV programming

在前兩篇文章  camera calibration -part1 camera model 以及 camera calibration -part2 camera calibration 中介紹了 camera 內部參數(intrinsic parameter) , 形變參數 (distortion parameter) 以及校正的方法和原理, 本文說明如何使用 OpenCV 實作camera校正 程序.
校正的程序分為兩部分;


2012年10月23日 星期二

攝像頭校正 camera calibration - part 2 calibration


Lens Distortion

在前一篇文章 攝像頭校正 camera calibration - part 1 camera model提到 使用 lens 的好處是可以增加進光量, 縮短曝光時間. 但是缺點則是會造成非線性的影像形變.

常見的兩種主要形變, 分別是徑向( radial distortion)以及 切向形變 (tangent distortion). 徑向形變是由於 lens 的形狀, 使得距離lens中心越遠的光線在通過 lens時彎折較大越靠近 lens 中心的光線則彎折越小切向形變則是由 camera 模組組裝的誤差造成的. 主要是 lens sensor 並非平行對齊. 圖一是兩種形變的影像.


2012年9月14日 星期五

擴增實境 - A simple Augmented Reality demo


A simple Augmented Reality demo

最近研究了一個有趣的主題 : Augmented Reality ; AR, 中文翻譯為 擴增實境. 並且用目前的研究心得寫了一個簡單的 demo program.

這是一個 使用 marker 的 AR demo program. 其原理是使用 webcam 抓取影像, 對影像做 marker detection, 根據四邊形的 marker 在 2D image 上的形變狀況 推導出 marker 所在之 3D 平面的 3D transform. 然後使用此 3D transform, 在抓取的影像中繪制 3D 物件. 如此, 就把真實的影像 和虛擬的物件融合在一起.


2012年9月8日 星期六

攝像頭校正 camera calibration - part 1 camera model

PART 1 Camera Model


所謂 Camera model 是使用幾何(geometry)的方式描述真實世界中的物體在 camera 影像平面上的成像方式. 本文會說明最基本的 camera model, 也就是針孔攝像頭模型(pinhole camera model). 另外, 使用鏡片(lens)可以增加進入成像平面的單位時間光線總量,因此縮短了曝光所需要的時間, 但是使用lens也造成了影像或多或少產生了畸變(distortions), 因此我們還需要了解 lens distortion model.
有了camera 的 geometry model 以及 lens 的 distortion model 就可以建構完整的 camera 的內部參數(intrinsic parameter),   camera calibration 需要使用到 camera 的內部參數.


2012年7月21日 星期六

OpenCV 影像擷取 - 使用 DirectShow


在本篇文章中, 筆者將說明如何使用 DirectShow  擷取影像. 當初使用 DirectShow 是因為
需要從事 Stereo vision相關的研究, 要從多個 camera 擷取影像, 且使用 OpenCV 2.2版, 但是這一版的 OpenCV 原生函式無法正確的擷取多個 camera 的影像. 因此才改用 DirectShow.

2012年7月14日 星期六

OpenCV 影像擷取


本文介紹如何使用 OpenCV 進行影像擷取,  在前一篇文章中 Hello_OpenCV 從檔案將圖檔讀入並且顯示, 現在, 我們進一步擴充 Hello_OpenCV, 把原先的從檔案讀取圖檔改成從 WebCAM 擷取影像.
OpenCV 提供的影像擷取函式有兩個, 分別是
                               CvCapture* cvCaptureFromCAM(int index);
以及
                               IplImage* cvQueryFrame( CvCapture* capture );

2012年7月7日 星期六

OpenCV 開發環境設定


OpenCV 是一計算機視覺開源函式庫, 欲使用OpenCV 開發影像處理或是計算機視覺相關應用之前, 必須將最基本開發環境設定好.

本文介紹   Visual studio 2010 開發環境設定. 使用的 OpenCV 版本是 2.2 版. 包含以下主題
  1. 下載 OpenCV函式庫
  2. 安裝 
  3. 設定函式庫以及標頭檔路徑
  4. 一個簡單的 OpenCV 程式