四頂點校正透視變換的線性方程解(轉載)

来源:https://www.cnblogs.com/gispathfinder/archive/2019/10/28/11750683.html
-Advertisement-
Play Games

轉自 http://www.hanyeah.com/blog/post/%E5%9B%9B%E9%A1%B6%E7%82%B9%E6%A0%A1%E6%AD%A3%E9%80%8F%E8%A7%86%E5%8F%98%E6%8D%A2%E7%9A%84%E7%BA%BF%E6%80%A7%E6%96... ...


轉自 http://www.hanyeah.com/blog/post/%E5%9B%9B%E9%A1%B6%E7%82%B9%E6%A0%A1%E6%AD%A3%E9%80%8F%E8%A7%86%E5%8F%98%E6%8D%A2%E7%9A%84%E7%BA%BF%E6%80%A7%E6%96%B9%E7%A8%8B%E8%A7%A3.html


設計給了兩張圖,一張俯視圖A,一張側視圖B,要把A上的點映射到B上,B上的點映射到A上。怎麼做?

只有兩張圖

image


我們可以通過工具,獲取每張圖4個頂點的坐標,坐標之間必然存在映射關係,Pa = f(Pb),用矩陣表示,Pa = m*Pa。我們要求m。m用3*3的矩陣。

參考:https://www.cnblogs.com/faith0217/articles/5027490.html


透視變換(Perspective Transformation)用於解決仿射變換(Affine Transformation)無法改變形狀內部的相對位置關係的問題。類似Photoshop中的“自由變換”功能,或者GIMP中的“透視”功能,都可以用透視變換矩陣來實現。

現在給定2個四邊形:Poly1={{x1, y1}, {x2, y2}, {x3, y3}, {x4, y4}}、Poly2={{u1, v1}, {u2, v2}, {u3, v3}, {u4, v4}},求做一個透視變換Matrix,滿足Poly1的點能夠變形(Warp)到Poly2中的點。

透視變換矩陣的形式為:


image



顯然,我們需要求解的只是矩陣中8個未知量;已知量包括四邊形的4個頂點 x 2個坐標(x, y),一共是8個方程,數量剛剛好。對於每個頂點坐標,Poly1中的點總是通過下麵的方程轉換到Poly2中:


image


問題的關鍵在於,上面的公式需要求解非線性方程。因此,在解決Homography的問題上,常常用最小二乘法(Least Squares)求得參數估計。

其實稍加分析就不難發現,上面那個使用了分式的所謂“非線性方程”,實際上可以變形為:

image



它居然變成了線性方程!看來一切試圖用Newton迭代的演算法都是沒有必要的,因為我們可以用最簡單的線性代數來解決:


image


下麵是我用matlab計算的代碼,mat就是我們要求的矩陣,順便把mat的逆矩陣mat2也求出來,逆變換也有了。

沒有matlab也沒關係,運算不難,矩陣運算的庫也不難找。



u1 = 0;
v1 = 0;
u2 = 1000;
v2 = 0;
u3 = 1000;
v3 = 1000;
u4 = 0;
v4 = 1000;
x1 = -375;
y1 = 510;
x2 = 254;
y2 = 152;
x3 = 1134;
y3 = 304;
x4 = 782;
y4 = 828;

a = [
    x1, y1, 1,  0,  0,  0,  -x1*u1, -y1*u1;
    0,  0,  0,  x1, y1, 1,  -x1*v1, -y1*v1;
    x2, y2, 1,  0,  0,  0,  -x2*u2, -y2*u2;
    0,  0,  0,  x2, y2, 1,  -x2*v2, -y2*v2;
    x3, y3, 1,  0,  0,  0,  -x3*u3, -y3*u3;
    0,  0,  0,  x3, y3, 1,  -x3*v3, -y3*v3;
    x4, y4, 1,  0,  0,  0,  -x4*u4, -y4*u4;
    0,  0,  0,  x4, y4, 1,  -x4*v4, -y4*v4
    ];
u = [u1,v1,u2,v2,u3,v3,u4,v4]';
m = a\u;

mat = [m(1),m(2),m(3);m(4),m(5),m(6);m(7),m(8),1];
mat2 = inv(mat);


最後求出來結果是

mat =

         0.622681800333835         -2.26554353140329          1388.93287614087
          1.22602742955981          2.15410964579083         -638.835633268398
      1.38327614714492e-06       0.00133144792441439                         1
      
      
mat2 =

         0.434597104229077          0.59516884730679         -223.411138468529
        -0.177460145184904        0.0897866610409582            303.8391483172
      0.000235677774164818     -0.000120369546353085         0.595763035916078


可以用mat*[x1,y1,1]來驗證結果的正確性。


-------------------------------------------------------------------------------------

C#求解方法(應用Math.NET庫)

-------------------------------------------------------------------------------------

            double u1 = pEnvelope.MinX;
            double v1 = pEnvelope.MinY;
            double u2 = pEnvelope.MaxX;
            double v2 = pEnvelope.MinY;
            double u3 = pEnvelope.MaxX;
            double v3 = pEnvelope.MaxY;
            double u4 = pEnvelope.MinX;
            double v4 = pEnvelope.MaxY;
            double x1 = results[0][0];
            double y1 = results[0][1];
            double x2 = results[1][0];
            double y2 = results[1][1];
            double x3 = results[2][0];
            double y3 = results[2][1];
            double x4 = results[3][0];
            double y4 = results[3][1];
            //            
            double[,] x =
            {
                    { x1, y1, 1,  0,  0,  0,  -x1*u1, -y1*u1 },
                    { 0,  0,  0,  x1, y1, 1,  -x1 * v1, -y1 * v1},
                    { x2, y2, 1,  0,  0,  0,  -x2 * u2, -y2 * u2},
                    { 0,  0,  0,  x2, y2, 1,  -x2 * v2, -y2 * v2},
                    { x3, y3, 1,  0,  0,  0,  -x3 * u3, -y3 * u3},
                    { 0,  0,  0,  x3, y3, 1,  -x3 * v3, -y3 * v3},
                    { x4, y4, 1,  0,  0,  0,  -x4 * u4, -y4 * u4},
                    { 0,  0,  0,  x4, y4, 1,  -x4 * v4, -y4 * v4}
                };
            var matrixX = DenseMatrix.OfArray(x);
            var vectorB = new DenseVector(new[] { u1, v1, u2, v2, u3, v3, u4, v4 });
            var resultX = new DenseVector(8);
            matrixX.GramSchmidt().Solve(vectorB, resultX);
            //驗證
            //Console.WriteLine(x1 + ",  " + y1 + ",  " + x2 + ",  " + y2 + ",  " + x3 + ",  " + y3 + ",  " + x4 + ",  " + y4);
            //Console.WriteLine(u1 + ",  " + v1 + ",  " + u2 + ",  " + v2 + ",  " + u3 + ",  " + v3 + ",  " + u4 + ",  " + v4);            
            //Console.WriteLine(resultX);
            //var u = (resultX[0] * x1 + resultX[1] * y1 + resultX[2]) / (resultX[6] * x1 + resultX[7] * y1 + 1);
            //Console.WriteLine(u1 + "   " + u);
            double[] result = new double[] { resultX[0], resultX[1], resultX[2], resultX[3], resultX[4], resultX[5], resultX[6], resultX[7], 1 };

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 隨著互聯網時代的不斷發展,開發者可能會面臨這樣的困境:為瞭解決問題、提升開發效率而竭力研發出來的“創新”,似乎削弱了他們在公司的重要程度,甚至取代了他們原先的地位。比如,在雲原生時代,部分企業更願意選擇 K8s 來解決運維、彈性的問題,而不是組建一支需要耗費大量雇佣資金、管理資金的研發團隊。 對於 ...
  • 對於剛入門的Pythoner在學習過程中運行代碼是或多或少會遇到一些錯誤,剛開始可能看起來比較費勁。隨著代碼量的積累,熟能生巧當遇到一些運行時錯誤時能夠很快的定位問題原題。下麵整理了常見的17個錯誤,希望能夠幫助到大家。 1、忘記在if,for,def,elif,else,class等聲明末尾加 : ...
  • 【ASP.NET Core學習】基礎知識,配置文件,日誌,依賴註入 ...
  • 動手造輪子:實現一個簡單的依賴註入(一) Intro 在上一篇文章中主要介紹了一下要做的依賴註入的整體設計和大概編程體驗,這篇文章要開始寫代碼了,開始實現自己的依賴註入框架。 類圖 首先來溫習一下上次提到的類圖 服務生命周期 服務生命周期定義: 服務定義 服務註冊定義: 為了使用起來更方便添加了一些 ...
  • 描述:某次更新程式,需要給測試員MM測試,之前都是正常的,更新後給MM測試就報異常System.Net.WebException 基礎連接已經關閉:接收時發生錯誤 > System.IO.IOException: 無法從傳輸連接中讀取數據:你的主機中的軟體中止了一個已建立的連接。 排查第一步:首先用 ...
  • # 導包 首先我們需要導入 MailKit NuGet包,NuGet安裝包命令在下方拓展介紹中。 # 引用命名空間 # 郵件發送幫助類 藉助這一個簡單的郵件發送類我們就可以已經可以實現郵件發送功能了。 # 拓展(NuGet常用命令) 1、安裝指定版本:install-package <程式包名> - ...
  • 場景 SpringBoot+Junit在IDEA中實現查詢資料庫的單元測試: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/92780716 SSM中怎樣使用JUnit4+spring-test編寫單元測試: https://bl ...
  • 很高興地分享一個名稱為Aspose.Tasks for C ++的API全新發佈!Aspose.Tasks(用C ++編寫)旨在與C ++語言一起用於Windows,Linux和UNIX等各種平臺。Aspose.Tasks可以與任何類型的應用程式一起使用,從基於控制台的應用程式到基於桌面的應用程式。 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...