【數字圖像處理】圖像幾何變換之 圖像的極座標變化展開魚眼圖

在這裏插入圖片描述

(一)基礎知識

極座標變換及其反變換的關鍵在於,根據極座標變換前的圖像(我們稱爲“方圖”)確定極座標變換後的圖像(我們稱爲“圓圖”)上每個像素點的像素值。也即是找到“圓圖”和“方圖”間幾何座標的對應關係。

1、極座標變換

原理:
如下圖所示,實現極座標變換的關鍵即在於找到圓圖上任一點P(i,j),在方圖上對應的點p(m,n),然後通過插值算法實現圓圖上所有像素點的賦值。
方圖上,其行列數分別爲M、N,方圖上的每一列對應爲圓圖上的每條半徑,半徑方向存在着一個長度縮放因子delta_r = M/R,圓周方向被分爲N等分,即角度因子爲delta_t = 2π/N;
圓圖上,圖像座標(i,j)和世界座標(x,y)有着如下變換關係:x = j - R, y = R - i;
那麼,圖中P點半徑長度爲r = sqrt(xx + yy),角度theta = arctan(y/x);
圓圖上點P在方圖上對應行數爲r/delta_r;
圓圖上點P在方圖上對應的列數n = thata/delta_t。
在這裏插入圖片描述

圖像變換過程可以參考

  1. 圖像的極座標變換
  2. 圖像極座標變換
  3. 虹膜圖像處理程序

(二)軟件設計

因爲這個代碼時應用於嵌入式平臺必須考慮到計算速度的問題,所以這裏我們自己實現三角函數的近似計算缺點在於,邊界點可能會出現失真。

/**
 * @fn  float fastSin(float x)
 *
 * @brief   自定義快速變換 sin  cos  函數  定義 而外精度 更高擬合效果 參考鏈接
 *          https://www.cnblogs.com/sun11086/archive/2009/03/20/1417944.html
 *
 * @author  IRIS_Chen
 * @date    2019/6/17
 *
 * @param   x   The x coordinate
 *
 * @return  A float
 */
//本質上是利用了一個已經擬合好的二次函數近似三角函數
float fastSin(float x)
{
    float y;
    // 限定 x 在 -Pi  到 pi
    while (x < - PI)
    {
        x += (float)(2 * PI);
    }
    while (x > PI)
    {
        x -= (float)(2 * PI);
    }

    const float B = 1.2732; // 4 / CV_PI;
    const float C = -0.4053; // -4 / (CV_PI*CV_PI);
    if(x>0)
    {
    y = B * x + C * x * x;
    }
    else
    {
     y = -1*B * x + C * x * x;
    }
    return y;
}


/**
 * @fn  float fastCos(float x)
 *
 * @brief   Fast cosine
 *
 * @author  IRIS_Chen
 * @date    2019/6/17
 *
 * @param   x   The x coordinate
 *
 * @return  A float
 */
float fastCos(float x)
{
    return fastSin(x + 1.5707);
}

Mat creatMapMat(Mat src, 
                 int rows_c,
                 int cols_c,
                 double startdelta)
{
    Mat dst;
    int i,j;
    u8* inaddr;
    u8* outaddr;
    int polar_d =src.width;
    double polar_r = polar_d / 2.0;
    printf("1");
    dst=create("..\\picture\\test.bmp",cols_c,rows_c,3);
	double delta_r = polar_r / rows_c; //半徑因子
	double delta_t = 2.0*PI / cols_c;  //角度因子
	double center_polar_x = (polar_d - 1) / 2.0;
	double center_polar_y = (polar_d - 1) / 2.0;
    printf("2");
    for (i = 0; i < cols_c; i++)
	{
		double theta_p = i * delta_t+startdelta; //方圖第i列在圓圖對應線的角度
		double sin_theta = fastSin(theta_p);
		double cos_theta = fastCos(theta_p);
 
		for (int j = 0; j < rows_c; j++)
		{
			double temp_r = j * delta_r; //方圖第j行在圓圖上對應的半徑長度
 
			int polar_x = (int)(center_polar_x + temp_r * cos_theta);
			int polar_y = (int)(center_polar_y - temp_r * sin_theta);
            if(i<dst.width&&j<dst.highth&&polar_x<src.width&&polar_y<=src.highth)
            {
            inaddr=at(&dst,i,j);
            outaddr=at(&src,polar_x,polar_y);
            *inaddr=*outaddr;
            *(inaddr+1)=*(outaddr+1);
            *(inaddr+2)=*(outaddr+2);
            }
		}
	}
    return dst;
}

(三)應用舉例

/*************************************************
Copyright © Yueyang Co. Ltd. 2019-2029. All rights reserved.
File name: cv.h
Author: Yueyang
Version: V1.0
Description: LiteCV運行主函數
Others: 
Log: 11.3 Yueyang
*************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>

#include "bmp.h"
#include "cv.h"
#include "GeoTrans.h"
#include "PointOr.h"
#include "BasicGui.h"

int main()
{
     Mat src;
     Mat_Init();
     src=load("..\\picture\\hole.bmp");

     Mat dst=dst=creatMapMat(src, 500,500,PI/4);

     save("..\\picture\\test.bmp",&dst);

     show(&dst);

     destory(&src);
     destory(&dst);
      return 0; 
}

原圖:
這是一張醫學中使用的人的血管內壁照片:

在這裏插入圖片描述

變換後:

在這裏插入圖片描述

(四)寫在後面

因爲LiteCV項目纔剛剛寫了一個開頭,代碼中有錯誤的地方還望指出。我已經將項目同步到了github,我會實時更新這個代碼倉庫。
項目github地址:
LITECV

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章