日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

图像腐蚀 java_OpenCV3 图像膨胀 dilate、腐蚀 erode、提取图像中的条形码 JAVA 实现...

發(fā)布時間:2025/3/19 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 图像腐蚀 java_OpenCV3 图像膨胀 dilate、腐蚀 erode、提取图像中的条形码 JAVA 实现... 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

關(guān)于 JAVA 學(xué)習(xí) OpenCV 的內(nèi)容,函數(shù)講解,案例代碼內(nèi)容我均整理在 GitHub【OpenCV3-Study-JAVA 】上

下面代碼中所需的項目結(jié)構(gòu),圖片,請訪問 GitHub 獲取。

代碼展示

package opencv;

import opencv.base.OpenCVStudyBase;

import org.junit.Test;

import org.opencv.core.*;

import org.opencv.imgcodecs.Imgcodecs;

import org.opencv.imgproc.Imgproc;

import java.util.ArrayList;

import java.util.List;

/**

* @Author : alexliu

* @Description : 主要學(xué)習(xí)

* 1. 圖像腐蝕

* 2. 圖像膨脹

* 3. 查找條形碼案例

*/

public class StudyTest_8 extends OpenCVStudyBase{

/*

* 腐蝕,膨脹都屬于形態(tài)學(xué)濾波。

*

* 數(shù)學(xué)形態(tài)學(xué)中,基本的運算有:

* 二值腐蝕和膨脹

* 二值開閉運算

* 骨架抽取

* 極限腐蝕

* 灰值腐蝕和膨脹

* 灰值開閉運算

* 灰值形態(tài)學(xué)梯度

* .....

*

*

* 腐蝕,膨脹的主要功能如下:

* 1. 消除噪聲

* 2. 分割(isolate)出獨立的圖像元素,在圖像中連接(join)相鄰的元素

* 3. 尋找圖像中的明顯的極大值區(qū)域或極小值區(qū)域

* 4. 求出圖像的梯度

*

* 注意:

* 腐蝕和膨脹僅針對`圖像高亮`區(qū)域進行操作。

*

*/

private String save_dir = "study-output/study-opencv-8";

/*

* 如何創(chuàng)建腐蝕、膨脹操作的核

*

* 腐蝕和膨脹均有一個 Mat kernel 參數(shù)。這個參數(shù)就是腐蝕/膨脹操作的核,它是一個矩陣結(jié)構(gòu)元素(Mat)

* OpenCV 在 Imgproc 包中,提供了 getStructuringElement 的函數(shù),來方便創(chuàng)建腐蝕/膨脹的核

*

* getStructuringElement 原型方法:

* getStructuringElement(int shape, Size ksize, Point anchor)

* getStructuringElement(int shape, Size ksize)

*

* 參數(shù):

* shape : Integer 核的結(jié)構(gòu)類型

* -- C++ 有四種(多一個用戶自定義),其他語言3種

* -- MORPH_RECT , 一個矩形結(jié)構(gòu)元素

* -- MORPH_ELLIPSE , 一個橢圓結(jié)構(gòu)元素

* -- MORPH_CROSS , 一個十字形結(jié)構(gòu)元素

* ksize : Size 結(jié)構(gòu)元素的大小

* anchor : Point 元素中瞄點的位置。默認值 (-1,-1)表示在元素的中心位置。注意:只有十字形結(jié)構(gòu)元素依賴瞄點,其他形狀類型僅僅影響結(jié)果的偏移。

*

* 原文:

* shape – Element shape that could be one of the following:

* MORPH_RECT - a rectangular structuring element

* MORPH_ELLIPSE - an elliptic structuring element, that is, a filled ellipse inscribed into the rectangle Rect(0, 0, esize.width, 0.esize.height)

* MORPH_CROSS - a cross-shaped structuring element

* CV_SHAPE_CUSTOM - custom structuring element (OpenCV 1.x API)

* ksize – Size of the structuring element.

* anchor – Anchor position within the element. The default value (-1, -1) means that the anchor is at the center.

* Note that only the shape of a cross-shaped element depends on the anchor position.

* In other cases the anchor just regulates how much the result of the morphological operation is shifted.

*/

/*

* ------------------------------------------------------------------------------------------------------------

*

* 腐蝕

*

* 1. 腐蝕說明:

* 圖像的一部分區(qū)域與指定的核進行卷積,求核的最`小`值并賦值給指定區(qū)域。

* 腐蝕可以理解為圖像中`高亮區(qū)域`的'領(lǐng)域縮小'。

* 意思是高亮部分會被不是高亮部分的像素侵蝕掉,使高亮部分越來越少。

*

* 2. 腐蝕函數(shù)(erode)

* erode 有3個原型方法

*

* erode(Mat src, Mat dst, Mat kernel, Point anchor, int iterations, int borderType, Scalar borderValue)

* erode(Mat src, Mat dst, Mat kernel, Point anchor, int iterations)

* erode(Mat src, Mat dst, Mat kernel)

*

* 參數(shù):

* src : Mat 輸入圖像 對通道數(shù)無要求,但是 depth 必須是 CV_8U、CV_16U、CV_16S、CV_32F、CV_64F 之一

* dst : Mat 輸出圖像,與原圖以上的尺寸與類型

* kernel : Mat 膨脹操作的核 , null 時表示以當前像素為中心 3x3 為單位的核

* 一般使用函數(shù) Imgproc.getStructuringElement 來創(chuàng)建核。該函數(shù)會返回指定形狀或尺寸的矩陣結(jié)構(gòu)元素。

* anchor : Point 瞄點。根據(jù) kernel(核),處理每個核的某個點。 (-1,-1)代表取這個核的中心位置。

* interations : Integer 迭代 dilate(膨脹)的次數(shù),默認 1 。。

* borderType : Integer 推斷圖像外部像素的某種邊界模式,一般不需要這個參數(shù)。

* borderValue : Scalar 當 borderType 值為常數(shù)時,區(qū)域的顏色一般不用管,

*

* 腐蝕,一般不需要borderType,borderValue,均有默認值。如果需要使用,可參考官網(wǎng)獲取更多信息

*

* ------------------------------------------------------------------------------------------------------------

*/

/**

* 圖像腐蝕處理

* 不做任何處理的圖片

*/

@Test

public void testErodeNomal(){

Mat sourceImage = Imgcodecs.imread(p_test_file_path + "/shufa.png");

//Mat sourceImage = Imgcodecs.imread(test_file_path + "/5cent.jpg",Imgcodecs.CV_LOAD_IMAGE_GRAYSCALE);

// size 越小,腐蝕的單位越小,圖片越接近原圖

Mat structImage = Imgproc.getStructuringElement(Imgproc.MORPH_RECT,new Size(30,30));

Mat outImage = new Mat();

//開始腐蝕

Imgproc.erode(sourceImage,outImage,structImage);

this.saveImage(this.save_dir + "/image_process_erode_nomal.png",outImage);

}

/**

* 圖像腐蝕處理

* 灰度處理的圖片

*/

@Test

public void testErodeGray(){

// 由于shufa.png 背景為白色,字體為黑色,在灰度的0-255顯示范圍,看不出變化

// 所以我們換一個背景圖不是白色的。

Mat sourceImage = Imgcodecs.imread(p_test_file_path + "/shufa-1.jpg",Imgcodecs.CV_LOAD_IMAGE_GRAYSCALE);

Mat structImage = Imgproc.getStructuringElement(Imgproc.MORPH_ELLIPSE,new Size(30,30));

Mat outImage = new Mat();

Imgproc.erode(sourceImage,outImage,structImage);

this.saveImage(this.save_dir + "/image_process_erode_gray.png",outImage);

}

/**

* 圖像腐蝕處理

* 二值化處理的圖片

*/

@Test

public void testErodeThreshold() {

Mat sourceImage = Imgcodecs.imread(this.p_test_file_path + "/shufa.png");

//二值化處理 cv_8uc1 8位單通道格式

Mat binaryMat = new Mat(sourceImage.height(), sourceImage.width(), CvType.CV_8UC1);

Imgproc.threshold(sourceImage, binaryMat,100, 200, Imgproc.THRESH_BINARY);

Mat outImage = new Mat();

//圖像腐蝕

Mat structImage = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(30,30));

Imgproc.erode(binaryMat, outImage, structImage);

this.saveImage(this.save_dir + "/image_process_erode_threshold.png",outImage);

}

/*

* ------------------------------------------------------------------------------------------------------------

*

* 膨脹

*

* 1. 膨脹說明:

* 圖像的一部分區(qū)域與指定的核進行卷積,求核的最`大`值并賦值給指定區(qū)域。

* 膨脹可以理解為圖像中`高亮區(qū)域`的'領(lǐng)域擴大'。

* 意思是高亮部分會侵蝕不是高亮的部分,使高亮部分越來越多。

*

* 2. 膨脹函數(shù)(dilate)

* dilate 有3個原型方法

*

* dilate(Mat src, Mat dst, Mat kernel, Point anchor, int iterations, int borderType, Scalar borderValue)

* dilate(Mat src, Mat dst, Mat kernel, Point anchor, int iterations)

* dilate(Mat src, Mat dst, Mat kernel)

*

* 參數(shù):

* src : Mat 輸入圖像 對通道數(shù)無要求,但是 depth 必須是 CV_8U、CV_16U、CV_16S、CV_32F、CV_64F 之一

* dst : Mat 輸出圖像,與原圖以上的尺寸與類型

* kernel : Mat 膨脹操作的核 , null 時表示以當前像素為中心 3x3 為單位的核

* 一般使用函數(shù) Imgproc.getStructuringElement 來創(chuàng)建核。該函數(shù)會返回指定形狀或尺寸的矩陣結(jié)構(gòu)元素。

* anchor : Point 瞄點。根據(jù) kernel(核),處理每個核的某個點。 (-1,-1)代表取這個核的中心位置。

* interations : Integer 迭代 dilate(膨脹)的次數(shù),默認 1 。。

* borderType : Integer 推斷圖像外部像素的某種邊界模式,一般不需要這個參數(shù)。

* borderValue : Scalar 當 borderType 值為常數(shù)時,區(qū)域的顏色一般不用管,

*

* 膨脹,一般不需要borderType,borderValue,均有默認值。如果需要使用,可參考官網(wǎng)獲取更多信息

*

* ------------------------------------------------------------------------------------------------------------

*/

/**

* 圖像膨脹處理

* 不做任何處理的圖片

*/

@Test

public void testDilateNomal(){

Mat sourceImage = Imgcodecs.imread(this.p_test_file_path + "/shufa.png");

Mat outImage = new Mat();

//圖像腐蝕

Mat structImage = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(30,30));

Imgproc.dilate(sourceImage, outImage, structImage);

this.saveImage(this.save_dir + "/image_process_dilate_nomal.png",outImage);

}

/**

* 圖像膨脹處理

* 灰度處理的圖片

*/

@Test

public void testDilateGray(){

Mat sourceImage = Imgcodecs.imread(this.p_test_file_path + "/shufa-1.jpg",Imgcodecs.CV_LOAD_IMAGE_GRAYSCALE);

Mat outImage = new Mat();

//圖像腐蝕

Mat structImage = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(30,30));

Imgproc.dilate(sourceImage, outImage, structImage);

this.saveImage(this.save_dir + "/image_process_dilate_gray.png",outImage);

}

/**

* 圖像膨脹處理

* 二值化處理的圖片

*/

@Test

public void testDilateThreshold() {

Mat sourceImage = Imgcodecs.imread(this.p_test_file_path + "/shufa.png");

//二值化處理 cv_8uc1 8位單通道格式

Mat binaryMat = new Mat(sourceImage.height(), sourceImage.width(), CvType.CV_8UC1);

Imgproc.threshold(sourceImage, binaryMat,100, 200, Imgproc.THRESH_BINARY);

Mat outImage = new Mat();

//圖像腐蝕

Mat structImage = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(30,30));

Imgproc.dilate(binaryMat, outImage, structImage);

this.saveImage(this.save_dir + "/image_process_dilate_threshold.png",outImage);

}

/**

* 查找條形碼案例

*

* 步驟:

* 1. 讀取灰值圖

* 2. 圖像模糊,降噪

* 3. 圖像二值化

* 4. 腐蝕圖像,通過腐蝕過濾掉不是豎線的的區(qū)域

* 5. 膨脹圖像,將腐蝕過的線條數(shù)據(jù)通過膨脹放大

* 6. 繼續(xù)用矩形核膨脹圖像,使線條鏈接成矩形圖像

* 7. 查找輪廓

* 8. 對比所有輪廓,過濾掉寬度小于200,偏斜角<2度的矩形圖像

* 9. 找到圖像并截取

*/

@Test

public void testFindLineCode() {

//讀取灰值圖

Mat sourceImage = Imgcodecs.imread(this.p_test_file_path + "/tiaoma.png",Imgcodecs.CV_LOAD_IMAGE_GRAYSCALE);

//圖像高斯模糊

Mat gsMat = Mat.ones(sourceImage.size(),sourceImage.type());

Imgproc.GaussianBlur(sourceImage,gsMat,new Size(5,5),0,0);

this.saveImage(this.save_dir + "/image_process_dilate_tiaoma-1.png",gsMat);

//圖像二值化,adaptiveThreshold 后面再二值化的專題里講解

Mat thresh_image = Mat.ones(sourceImage.size(),sourceImage.type());

// C 負數(shù),取反色,超過閾值的為黑色,其他為白色

Imgproc.adaptiveThreshold(gsMat, thresh_image,255, Imgproc.ADAPTIVE_THRESH_MEAN_C, Imgproc.THRESH_BINARY,7,-2);

this.saveImage(this.save_dir + "/image_process_dilate_tiaoma-2.png",thresh_image);

//創(chuàng)建輸出圖像,后續(xù)的操作都是這個圖像

Mat outImage = new Mat();

/*

* 圖像腐蝕操作

*

* width=2 ,height=20 在腐蝕的時候,排除大多數(shù)細的垂直線。

* 這個參數(shù)不易設(shè)置過大,可以通過多次腐蝕來達到排除的效果。

*

* ----------------------------------------------------------------------------------

* 注意 width、height 需根據(jù)圖像的大小來設(shè)置。

*

* 比如我這里的示例圖片大小是 1271(width)x648(height)。 我通過比較20是比較理想的值。

* 但是20 并比適用比示例圖小或大的圖像。所以在設(shè)置這個參數(shù)前,需要根據(jù)圖像大小來調(diào)整。

*

* && 這個值沒有固定、動態(tài)的大小,不要期望自動設(shè)置,除非接入 AI 來學(xué)習(xí)。 &&

*

* 但是我們加入到自己工程的業(yè)務(wù)里,我們處理的圖片通常都是固定的幾個圖像大小

*

* 比如攝像頭獲取圖像,可以指定 500x500

* 比如掃描儀獲取圖像,可以指定 KPI 大小,那么獲取到的同等材質(zhì)(如 A4大小)的數(shù)碼圖片大小也是一樣的。

* 比如數(shù)碼照片,在不同模式下照片大小是一致的,可以根據(jù)圖片信息分類。

*

* 所以,自己根據(jù)自己業(yè)務(wù)經(jīng)常處理的圖片來設(shè)置一個比例參數(shù) ,通過 sourceImage.heigth()*xParam 來獲取這個參數(shù)即可。

* ----------------------------------------------------------------------------------

*/

Mat structImage = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(2,20));

Imgproc.erode(thresh_image, outImage, structImage,new Point(-1,-1),3); //腐蝕了3次

this.saveImage(this.save_dir + "/image_process_dilate_tiaoma-3.png",outImage);

// 在用腐蝕的圖像,進行膨脹,將線條加粗

Imgproc.dilate(outImage, outImage, structImage,new Point(-1,-1),3); // 這里同樣進行了3次膨脹

this.saveImage(this.save_dir + "/image_process_dilate_tiaoma-4.png",outImage);

/*

* 這里我劃定了一個10x5 的矩形整列。來將剩余的線條通過膨脹連成區(qū)域。

* 范圍同樣不宜過大或過小。

* 過大:膨脹區(qū)域增大,最終結(jié)果圖像干擾太多

* 過小:膨脹區(qū)域減少,可滿足的條件過多,造成不容易連成一個整理區(qū)域。

*/

// 再次膨脹,使其連成區(qū)域

structImage = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(10,5));

Imgproc.dilate(outImage, outImage, structImage,new Point(-1,-1),3);

this.saveImage(this.save_dir + "/image_process_dilate_tiaoma-5.png",outImage);

/*

* findContours 找輪廓

*

* 原型方法:

*

* findContours(Mat image, List contours, Mat hierarchy, int mode, int method, Point offset)

*

* image : Mat 是輸入圖像,圖像的格式是8位單通道的圖像,并且被解析為二值圖像(即圖中的所有非零像素之間都是相等的)。

* coutours : List 輸出的輪廓數(shù)組,所有找到的輪廓都會放在這個數(shù)組中。MatOfPoint代表這個對象存儲了輪廓的`點`數(shù)據(jù)

* hierarchy : Mat 這個參數(shù)可以指定,也可以不指定。

* 如果指定的話,輸出hierarchy,將會描述輸出輪廓樹的結(jié)構(gòu)信息。

* 0號元素表示下一個輪廓(同一層級);

* 1號元素表示前一個輪廓(同一層級);

* 2號元素表示第一個子輪廓(下一層級);

* 3號元素表示父輪廓(上一層級)

* mode : Integer 輪廓的模式,將會告訴OpenCV你想用何種方式來對輪廓進行提取,有四個可選的值:

* CV_RETR_EXTERNAL (0):表示只提取最外面的輪廓;

* CV_RETR_LIST (1):表示提取所有輪廓并將其放入列表;

* CV_RETR_CCOMP (2):表示提取所有輪廓并將組織成一個兩層結(jié)構(gòu),其中頂層輪廓是外部輪廓,第二層輪廓是“洞”的輪廓;

* CV_RETR_TREE (3):表示提取所有輪廓并組織成輪廓嵌套的完整層級結(jié)構(gòu)。

* method : Integer 輪廓如何呈現(xiàn)的方法,有三種可選的方法:

* CV_CHAIN_APPROX_NONE (1):將輪廓中的所有點的編碼轉(zhuǎn)換成點;

* CV_CHAIN_APPROX_SIMPLE (2):壓縮水平、垂直和對角直線段,僅保留它們的端點;

* CV_CHAIN_APPROX_TC89_L1 (3)or CV_CHAIN_APPROX_TC89_KCOS(4):應(yīng)用Teh-Chin鏈近似算法中的一種風(fēng)格

* offset : Point 可選,如果指定了點偏移,那么返回的輪廓中的所有點均作指定量的偏移

*/

List contours = new ArrayList();

Mat hierarchy = new Mat();

Imgproc.findContours(outImage,contours,hierarchy, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE,new Point(0,0));

// 根據(jù)輪廓可以找到的形狀數(shù)組

// Rect[] boundRect = new Rect[contours.size()];

// 循環(huán)找到的所有輪廓

for(int i = 0; i < contours.size();i++) {

//將輪廓保存為區(qū)域

// boundRect[i] = Imgproc.boundingRect(contours.get(i));

// System.out.println(boundRect[i].tl());

// System.out.println(boundRect[i].br());

// 獲取輪廓內(nèi),最小外包矩形

RotatedRect min = Imgproc.minAreaRect(new MatOfPoint2f(contours.get(i).toArray()));

//偏轉(zhuǎn)角度

if(min.angle < 2){

//獲取一個矩形

Rect minRect = min.boundingRect();

//將寬度<200的排除

if( ( minRect.br().x - minRect.tl().x ) > 200 ){

//截取

Mat code = sourceImage.submat(minRect);

this.saveImage(this.save_dir + "/image_process_dilate_tiaoma-code-"+i+".png",code);

}

//在原圖上把該矩形表示出來

Imgproc.rectangle(sourceImage, minRect.tl(), minRect.br(), new Scalar(0, 255, 0), 1, Imgproc.LINE_AA, 0);

}

}

//輸出原圖

this.saveImage(this.save_dir + "/image_process_dilate_tiaoma-6.png",sourceImage);

}

}

部分結(jié)果展示

膨脹 dilate

原圖:

膨脹后:

腐蝕 erode

獲取條形碼

獲取條形碼的效果可能不是最好,方法也不是最好的,只是我學(xué)到這里的一些積累。只是拋出一種方法而已。

廣告欄: 歡迎關(guān)注我的 個人博客

總結(jié)

以上是生活随笔為你收集整理的图像腐蚀 java_OpenCV3 图像膨胀 dilate、腐蚀 erode、提取图像中的条形码 JAVA 实现...的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。