圖像二值化就是將圖像上的像素點的灰度值設置爲0或255,也就是將整個圖像呈現出明顯的黑白效果。
將256個亮度等級的灰度圖像經過適當的閾值選取而得到仍然能夠反映圖像總體和局部特徵的二值化圖像。在數字圖像處理中,二值圖像佔有很是重要的地位,首先,圖像的二值化有利於圖像的進一步處理,使圖像變得簡單,並且數據量減少,能凸顯出感興趣的目標的輪廓。其次,要進行二值圖像的處理與分析,首先要把灰度圖像二值化,獲得二值化圖像。java
在實際應用中,不少圖像的分析最終都轉換爲二值圖像的分析,好比:醫學圖像分析、前景檢測、字符識別,形狀識別。二值化+數學形態學能解決不少計算機識別工程中目標提取的問題。git
開操做是先腐蝕後膨脹的過程。用來消除小物體、在纖細點處分離物體、平滑較大物體的邊界的同時並不明顯改變其面積。github
跟開操做相對應的是閉操做。另外,腐蝕和膨脹在下文中有介紹。算法
在 cv4j 中,咱們封裝好了這些形態學的經常使用操做,好比開閉操做、腐蝕和膨脹等等。網絡
其中,開操做的代碼以下:dom
public class MorphOpen {
/** * in order to remove litter noise block, erode + dilate operator * * @param binary * @param structureElement */
public void process(ByteProcessor binary, Size structureElement) {
Erode erode = new Erode();
Dilate dilate = new Dilate();
erode.process(binary, structureElement);
dilate.process(binary, structureElement);
}
}複製代碼
先來看一個完整demo的效果圖
post
第三步若是看不太清楚,咱們看一下放大的效果圖
spa
如上圖所示,demo完成了文本的切割。咱們來看看具體的代碼是怎麼實現的。.net
準備工做展現原圖3d
Resources res = getResources();
final Bitmap bitmap = BitmapFactory.decodeResource(res, R.drawable.test_binary1);
image0.setImageBitmap(bitmap);複製代碼
第一步二值化
CV4JImage cv4JImage = new CV4JImage(bitmap);
Threshold threshold = new Threshold();
threshold.process((ByteProcessor)(cv4JImage.convert2Gray().getProcessor()),Threshold.THRESH_TRIANGLE,Threshold.METHOD_THRESH_BINARY_INV,255);
image1.setImageBitmap(cv4JImage.getProcessor().getImage().toBitmap());複製代碼
第二步開操做
MorphOpen morphOpen = new MorphOpen();
cv4JImage.resetBitmap();
morphOpen.process((ByteProcessor)cv4JImage.getProcessor(),new Size(5));
image2.setImageBitmap(cv4JImage.getProcessor().getImage().toBitmap());複製代碼
第三步連通組件標記
ConnectedAreaLabel connectedAreaLabel = new ConnectedAreaLabel();
byte[] mask = new byte[cv4JImage.getProcessor().getWidth() * cv4JImage.getProcessor().getHeight()];
List<Rect> rectangles = new ArrayList<>();
connectedAreaLabel.process((ByteProcessor)cv4JImage.getProcessor(),mask,rectangles,true);
cv4JImage.resetBitmap();
Bitmap newBitmap = cv4JImage.getProcessor().getImage().toBitmap();
if (Preconditions.isNotBlank(rectangles)) {
Tools.drawRects(newBitmap,rectangles);
}
image3.setImageBitmap(newBitmap);複製代碼
其實,作完第三步再結合ocr就能夠識別出具體文字啦。若是再結合一下網絡爬蟲的話,意義更大。
雖然, cv4j 目前還只是移動端的庫,可是它畢竟是java開發的,改爲適合desktop的很容易。
腐蝕操做是一種消除邊界點,使邊界向內部收縮的過程。能夠用來消除小且無心義的物體。腐蝕操做掃描圖像的每個像素,用結構元素與其覆蓋的二值圖像作「與」操做:若是都爲1,結果圖像的該像素爲1,不然爲0。
跟腐蝕操做相對的是膨脹操做。腐蝕用於分割獨立的圖像元素,而膨脹用於鏈接相鄰的元素。
腐蝕的算法:
能夠簡化爲:
來看一個例子,原圖中有不少硬幣,經過一步步的分析計算出硬幣的個數。
準備工做展現原圖
Resources res = getResources();
final Bitmap bitmap = BitmapFactory.decodeResource(res, R.drawable.test_coins);
image0.setImageBitmap(bitmap);複製代碼
第一步二值化
CV4JImage cv4JImage = new CV4JImage(bitmap);
Threshold threshold = new Threshold();
threshold.process((ByteProcessor)(cv4JImage.convert2Gray().getProcessor()),Threshold.THRESH_OTSU,Threshold.METHOD_THRESH_BINARY_INV,255);
image1.setImageBitmap(cv4JImage.getProcessor().getImage().toBitmap());複製代碼
第二步腐蝕操做
Erode erode = new Erode();
cv4JImage.resetBitmap();
erode.process((ByteProcessor)cv4JImage.getProcessor(),new Size(3),10);
image2.setImageBitmap(cv4JImage.getProcessor().getImage().toBitmap());複製代碼
第三步連通組件標記
ConnectedAreaLabel connectedAreaLabel = new ConnectedAreaLabel();
byte[] mask = new byte[cv4JImage.getProcessor().getWidth() * cv4JImage.getProcessor().getHeight()];
int num = connectedAreaLabel.process((ByteProcessor)cv4JImage.getProcessor(),mask,null,false); // 獲取連通組件的個數
SparseIntArray colors = new SparseIntArray();
Random random = new Random();
int height = cv4JImage.getProcessor().getHeight();
int width = cv4JImage.getProcessor().getWidth();
int size = height * width;
for (int i = 0;i<size;i++) {
int c = mask[i] & 0xff;
colors.put(c,Color.argb(255, random.nextInt(255),random.nextInt(255),random.nextInt(255)));
}
cv4JImage.resetBitmap();
Bitmap newBitmap = cv4JImage.getProcessor().getImage().toBitmap();
for(int row=0; row<height; row++) {
for (int col = 0; col < width; col++) {
int c = mask[row*width+col] & 0xff;
if (c>0) {
newBitmap.setPixel(col,row,colors.get(c));
}
}
}
image3.setImageBitmap(newBitmap);
if (num>0)
numTextView.setText(String.format("總計識別出%d個硬幣",num));複製代碼
最終獲取了連通組件的個數也就是硬幣的個數,而且在已經識別的硬幣上隨機着色。
#總結
cv4j 是gloomyfish和我一塊兒開發的圖像處理庫,純java實現,目前還處於早期的版本。這周,咱們開始作二值圖像的分析(腐蝕、膨脹、開閉操做、輪廓提取等等),這個模塊並無完成所有功能,預計下週能完工。