Java使用OpenCV計算兩張圖片相似度

業務:找出兩個表的重復的圖片。

圖片在表里存的是二進制值,存在大量由于一些特殊情況例如掃描有差異,導致圖片存的二進制值不同,但圖片其實是一樣來的。

所以找出兩個表重復相同的圖片,不可能只是單純的比較二進制值相等。

方法:針對這種情況,使用OpenCV直方圖算法可以比較兩張圖片的相似度,測試發現完全相同的圖片相似度等于1(表里存的二進制值不相等)

實操:Java引入使用opencv步驟詳解

1.引入opencv依賴

<!-- https://mvnrepository.com/artifact/org.openimaj/core -->
<dependency><groupId>org.openpnp</groupId><artifactId>opencv</artifactId><version>4.5.5-1</version>
</dependency>

2.代碼Demo

opencv提供了均方差算法(MSE)、結構相似性指數算法(SSIM)、峰值信噪比算法(PSNR)、直方圖算法(SSIM-WH),其中使用直方圖算法來比較圖片相似效果最好。

    public static void main(String[] args) {// 加載OpenCV庫System.loadLibrary(Core.NATIVE_LIBRARY_NAME);// 讀取兩張圖像。準備比對的圖片Mat image1 = Imgcodecs.imread("D:\\work\\testdata\\psc_1716260008343.jpg");Mat image2 = Imgcodecs.imread("D:\\work\\testdata\\psc_1716260008345.jpg");// 將圖片處理成一樣大Imgproc.resize(image1, image1, image2.size());Imgproc.resize(image2, image2, image1.size());// 計算均方差(MSE)double mse = calculateMSE(image1, image2);System.out.println("均方差(MSE): " + mse);// 計算結構相似性指數(SSIM)double ssim = calculateSSIM(image1, image2);System.out.println("結構相似性指數(SSIM): " + ssim);// 計算峰值信噪比(PSNR)double psnr = calculatePSNR(image1, image2);System.out.println("峰值信噪比(PSNR): " + psnr);// 計算直方圖final double similarity = calculateHistogram(image1, image2);System.out.println("圖片相似度(直方圖): " + similarity);// 計算歸一化交叉相關(NCC)
//        double ncc = calculateNCC(image1, image2);
//        System.out.println("歸一化交叉相關(NCC): " + ncc);}// 計算均方差(MSE)private static double calculateHistogram(Mat image1, Mat image2) {// 計算直方圖Mat hist1 = calculateHistogram(image1);Mat hist2 = calculateHistogram(image2);// 計算相似度final double similarity = Imgproc.compareHist(hist1, hist2, Imgproc.CV_COMP_CORREL);// 手動釋放內存
//        if (hist1 != null) {
//            hist1.release();
//        }
//        if (hist2 != null) {
//            hist2.release();
//        }return similarity;}// 計算均方差(MSE)private static double calculateMSE(Mat image1, Mat image2) {Mat diff = new Mat();Core.absdiff(image1, image2, diff);Mat squaredDiff = new Mat();Core.multiply(diff, diff, squaredDiff);Scalar mseScalar = Core.mean(squaredDiff);return mseScalar.val[0];}// 計算結構相似性指數(SSIM)private static double calculateSSIM(Mat image1, Mat image2) {Mat image1Gray = new Mat();Mat image2Gray = new Mat();Imgproc.cvtColor(image1, image1Gray, Imgproc.COLOR_BGR2GRAY);Imgproc.cvtColor(image2, image2Gray, Imgproc.COLOR_BGR2GRAY);MatOfFloat ssimMat = new MatOfFloat();Imgproc.matchTemplate(image1Gray, image2Gray, ssimMat, Imgproc.CV_COMP_CORREL);Scalar ssimScalar = Core.mean(ssimMat);return ssimScalar.val[0];}// 計算峰值信噪比(PSNR)private static double calculatePSNR(Mat image1, Mat image2) {Mat diff = new Mat();Core.absdiff(image1, image2, diff);Mat squaredDiff = new Mat();Core.multiply(diff, diff, squaredDiff);Scalar mseScalar = Core.mean(squaredDiff);double mse = mseScalar.val[0];double psnr = 10.0 * Math.log10(255.0 * 255.0 / mse);return psnr;}// 計算歸一化交叉相關(NCC)
//    private static double calculateNCC(Mat image1, Mat image2) {
//        Mat image1Gray = new Mat();
//        Mat image2Gray = new Mat();
//        Imgproc.cvtColor(image1, image1Gray, Imgproc.COLOR_BGR2GRAY);
//        Imgproc.cvtColor(image2, image2Gray, Imgproc.COLOR_BGR2GRAY);
//        MatOfInt histSize = new MatOfInt(256);
//        MatOfFloat ranges = new MatOfFloat(0, 256);
//        Mat hist1 = new Mat();
//        Mat hist2 = new Mat();
//
//        Core.normalize(hist1, hist1, 0, 1, Core.NORM_MINMAX);
//        Core.normalize(hist2, hist2, 0, 1, Core.NORM_MINMAX);
//        double ncc = Core.compareHist(hist1, hist2, Imgproc.CV_COMP_CORREL);
//        return ncc;
//    }private static Mat calculateHistogram(Mat image) {Mat hist = new Mat();// 設置直方圖參數MatOfInt histSize = new MatOfInt(256);MatOfFloat ranges = new MatOfFloat(0, 256);MatOfInt channels = new MatOfInt(0);List<Mat> images = new ArrayList<>();images.add(image);// 計算直方圖Imgproc.calcHist(images, channels, new Mat(), hist, histSize, ranges);return hist;}

3.運行遇到的報錯問題以及解決方法

Exception in thread "main" java.lang.UnsatisfiedLinkError: no opencv_java455 in java.library.path

報錯原因:

在JDK bin 目錄下找不到 opencv_java455.dll 文件

解決方法:

官網下載地址:Releases - OpenCV

找到對應的版本下載opencv(如果下載不起很慢,可以復制鏈接用迅雷下載)

雙擊打開安裝包選擇安裝提取目錄

等待解壓

在目錄找到dll文件

然后復制到jdk bin目錄中

再重新運行程序即可解決

4.運行

均方差算法(MSE):

計算兩幅圖片每個像素之間的差異,并計算它們的平均值。MSE值越小,表示兩幅圖片越相似。

結構相似性指數(SSIM):

通過比較兩幅圖片的亮度、對比度和結構信息來評估它們的相似性。值越大,越相似。

峰值信噪比(PSNR):

通過計算兩幅圖片的MSE值,并將其轉換為對數尺度,來評估它們的相似性。PSNR值越大,表示兩幅圖片越相似。

圖片相似度(直方圖):

通過將SSIM指數和直方圖相似性組合起來,來評估兩幅圖片的相似性。返回的相似性度量值越接近1,表示兩幅圖像越相似。

5.結合業務實現代碼片段

注:務必手動釋放Mat內存,親測不寫手動釋放內存,隨著循環量越多,創建Mat越多,就會導致內存崩潰泄露(按理說Java有回收機制,但我經過測試發現并沒有觸發回收內存,即使是沒用的Mat)

byte[] ecf2Image = bsImage.getImage();
byte[] upsImage = upsPage.getScanPage();
// 1.先直接對比ecf2和ups圖片的二進制值
if (Arrays.equals(ecf2Image, upsImage)) {// 二進制值相等則給ecf2圖片狀態更新為重復的updateAndRecord(shipmentNo, filename, upsPage, 1);// 然后跳出scanPageList的循環,已經確認為重復就不用再去匹配break;
}// 2.byte值不等,再用OpenCV來比較
// 將圖片二進制數據轉換為Mat對象
Mat image1 = Imgcodecs.imdecode(new MatOfByte(ecf2Image), Imgcodecs.IMREAD_COLOR);
Mat image2 = Imgcodecs.imdecode(new MatOfByte(upsImage), Imgcodecs.IMREAD_COLOR);
try {// 將圖片處理成一樣大Imgproc.resize(image1, image1, image2.size());Imgproc.resize(image2, image2, image1.size());// 計算直方圖final double similarity = calculateHistogram(image1, image2);if (similarity == 1) {// 更新狀態為重復的updateAndRecord(shipmentNo, filename, upsPage, 2);break;}
} catch (Exception e) {e.printStackTrace();
} finally {// 手動釋放內存if (image1 != null) {image1.release();}if (image2 != null) {image2.release();}
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/23976.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/23976.shtml
英文地址,請注明出處:http://en.pswp.cn/web/23976.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

flask招聘數據分析及展示平臺-計算機畢業設計源碼39292

目 錄 摘要 1 緒論 1.1研究意義 1.2國內外研究進展 1.3flask框架介紹 2 1.4論文結構與章節安排 3 2 招聘數據分析及展示平臺分析 4 2.1 可行性分析 4 2.2 系統流程分析 4 2.2.1數據增加流程 5 2.3.2數據修改流程 5 2.3.3數據刪除流程 5 2.3 系統功能分析 5 2.3.1 功能性分…

亞馬遜新品如何快速吸引流量?自養號測評助賣家一臂之力

在亞馬遜平臺上每天都會有大量的新品推出&#xff0c;而這些新品中有部分可能并沒有什么流量和訂單&#xff0c;有些可能上架后立馬就能獲得流量了&#xff0c;那么亞馬遜上新品一般幾天出單&#xff1f; 一、亞馬遜上新品一般幾天出單&#xff1f; 亞馬遜上新品出單的時間因…

DispatcherTimer應用

DispatcherTimer 是 WPF 中用于執行定時任務的類&#xff0c;用于在指定的時間間隔內執行任務。它與 UI 線程的 Dispatcher 相關聯&#xff0c;因此可以用來更新 UI 元素&#xff0c;而不必擔心線程安全問題。 關鍵特性&#xff1a; 線程安全&#xff1a;DispatcherTimer 確保…

人工智能時代,想轉型AI產品經理?這篇文章你不應該錯過

前言 在這個日新月異的智能時代&#xff0c;人工智能&#xff08;AI&#xff09;已經從未來概念轉變為推動各行各業發展的核心驅動力。作為連接技術與市場的橋梁&#xff0c;AI產品經理的角色愈發關鍵&#xff0c;他們不僅是技術的翻譯者&#xff0c;更是創新的推動者。如果你…

Mintegral解析休閑游戲如何靠創意素材吸引玩家

核心玩法簡單清晰、容易讓人無限上頭的休閑游戲&#xff0c;玩法機制一般比較明確、簡單&#xff0c;如果要在短時間內吸引玩家注意&#xff0c;除了完整展示游戲流程以外&#xff0c;開發者需要在素材中設置更多亮點性的內容&#xff0c;如吸睛的劇情、爆炸性的視聽效果等元素…

組件的注冊和引用

在Vue中&#xff0c;開發者可以將頁面中獨立的、可重用的部分封裝成組件&#xff0c;對組件的結構&#xff0c;樣式和行為進行設置。組件是 Vue 的基本結構單元&#xff0c;組件之間可以相互引用。 一.注冊組件 當在Vue項目中定義了一個新的組件后&#xff0c;要想在其他組件中…

Vue3_對接騰訊云COS_大文件分片上傳和下載

目錄 一、騰訊云后臺配置 二、安裝SDK 1.script 引入方式 2.webpack 引入方式 三、文件上傳 1.new COS 實例 2.上傳文件 四、文件下載 騰訊云官方文檔&#xff1a; 騰訊云官方文檔https://cloud.tencent.com/document/product/436/11459 一、騰訊云后臺配置 1.登錄 對…

[職場] 為什么不能加薪? #學習方法#知識分享#微信

為什么不能加薪&#xff1f; 不能加薪的根本原因&#xff0c;終于被我找到了&#xff01; 朋友們&#xff01;職場這個地方是個很神奇的世界&#xff0c;有些規則并不是你想象的那樣。我們都希望能在這個世界里施展自己的才華&#xff0c;獲得升職加薪的榮耀。然而&#xff0c…

seerfar丨OZON運營工具,OZON選品插件

隨著全球電商市場的蓬勃發展&#xff0c;OZON作為俄羅斯及東歐地區的重要電商平臺&#xff0c;吸引了眾多中國商家的目光。然而&#xff0c;如何在OZON平臺上脫穎而出&#xff0c;實現高效的商品運營&#xff0c;成為了眾多商家亟待解決的問題。在這樣的背景下&#xff0c;seer…

tailwindcss的@apply使用

tailwindcss的apply是把在html寫的tailwindcss可以挪到style里面 簡化頁面的可讀性 沒寫之前的 <section class"block-risk absolute flex flex-col items-center p-4 text-center left-0 text-white;" :style"{ top, left: 60px }"> </section…

淺析軟件開發技術的發展歷程與展望

隨著信息技術的飛速發展&#xff0c;軟件開發技術也在不斷演進。本文旨在深入探討軟件開發技術的發展歷程&#xff0c;并分析其未來的發展趨勢和展望。 軟件開發技術的發展歷程 在回顧軟件開發技術的發展歷程時&#xff0c;我們不禁驚嘆于這一領域的飛速進步。從早期的手工編寫…

被拖欠6000萬,代工大廠倒閉了····

6月7日消息&#xff0c;據綜合媒體報道&#xff0c;電子煙代工大廠佳斯特電子&#xff08;東莞&#xff09;發布公告&#xff0c;將自6月3日起停止一切經營活動&#xff0c;開始自行清算工作。根據佳斯特電子科技&#xff08;東莞&#xff09;有限公司的通告&#xff0c;由于公…

pyqt6 任務欄不顯示設置的icon

添加這段代碼即可解決 import ctypes myappid mycompany.myproduct.subproduct.version ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID(myappid)

TypeScript環境安裝與VScode編輯器的使用

說明大背景環境&#xff0c;我用的是window10系統。 1.安裝node.js 。 去官網下載安裝包。 雖然我去的是官網&#xff0c;但是不知為何下載了個不知名的東西&#xff0c;后來又找了個鏈接才下載正確了。 實際上就是一個.msi的文件。我用的版本&#xff1a;node-v18.19.0-x6…

最大矩形問題

柱狀圖中最大的矩形 題目 分析 矩形的面積等于寬乘以高&#xff0c;因此只要能確定每個矩形的寬和高&#xff0c;就能計算它的面積。如果直方圖中一個矩形從下標為 i 的柱子開始&#xff0c;到下標為 j 的柱子結束&#xff0c;那么這兩根柱子之間的矩形&#xff08;含兩端的柱…

能把試卷上的字消除的軟件有哪些?推薦三款好用的

能把試卷上的字消除的軟件有哪些&#xff1f;在數字化時代&#xff0c;我們越來越依賴科技手段來解決生活中的各種問題。其中&#xff0c;試卷上的字消除問題&#xff0c;就是一個備受關注的痛點。幸運的是&#xff0c;現在市面上已經出現了多款能夠輕松消除試卷上字跡的軟件&a…

力扣hot100:295. 數據流的中位數(兩個優先隊列維護中位數)

LeetCode&#xff1a;295. 數據流的中位數 這個題目最快的解法應該是維護中位數&#xff0c;每插入一個數都能快速得到一個中位數。 根據數據范圍&#xff0c;我們應當實現一個 O ( n l o g n ) O(nlogn) O(nlogn)的算法。 1、超時—插入排序 使用數組存儲&#xff0c;維持數…

【WEB自動化面試02--學習過程的問題及解決】

day01 1、報錯獲取不到瀏覽器二進制文件&#xff1a;需要指定瀏覽器路徑及驅動路徑。 第一次使用谷歌瀏覽器驅動&#xff0c;找不到二進制文件報錯&#xff1a; selenium.common.exceptions.WebDriverException: Message: unknown error: cannot find Chrome binary Stacktra…

短視頻矩陣源碼----如何做正規開發規則分享:

一、什么是SaaS化服務技術開發&#xff1f; &#xff08;短視頻矩陣系統是源頭開發的應該分為3個端口---- 總后臺控制端、總代理端口&#xff0c;總商戶后臺&#xff09; SaaS是軟件即服務&#xff08;Software as a Service&#xff09;的縮寫。它是一種通過互聯網提供軟件應…

Vue2(0基礎入門)

環境準備 安裝腳手架 vuecli: npm install -g vue/clivite: npm init vuelatest-g 全局安裝&#xff0c;任意目錄都可以使用vue腳本 進入目錄創建項目&#xff1a; 在目錄的終端輸入&#xff1a;vue ui安裝devtool(這個網頁是安裝好了自動跳轉的) 運行項目&#xff1a; …