2013-11-29 45 views
3

我有幾個彩色圖像的樣本,我應該變成二進制。我通過使用自適應閾值獲得了最佳結果。將圖像裁剪成片段然後加入,是否可以使用OpenCV?

這些數字非常好,定義明確,但周圍噪音很大,例如,將每個數字分開的這些「垂直線」最終被讀作OCR工具的數字1。

然後我注意到,在數字周圍的圖像是乾淨的。我想如果我只能剪出數字(在將圖片做成黑白之前或之後?),然後將這些數字粘貼到白色背景上。

我試圖將侵蝕擴張,但仍然有很多剩餘的「點」。如果我能做到我在想的那樣(上圖),那麼它會減少侵蝕/擴張,並增加切割前數字周圍的「清潔」,我不知道。

這可能嗎?我有意義嗎?如果是的話,我如何使用OpenCV來做到這一點?有什麼建議麼?

一些圖片,我使用:

rgb image1

image1 after adaptive threshold

rgb image2

image2 after adaptive threshold

注:的圖像上面都沒有通過的過程中走了erosio n和/或膨脹,僅適應性閾值處理。


更新:

@ Mahm00d,我想你的第一個圖像說什麼,我得到了下面的圖片,這是非常好的,但與前兩個數字反映的問題仍然存在。有沒有什麼辦法解決這一問題?我應用了自適應閾值,但圖像仍然很嘈雜。

高斯模糊+ Treshold與OTSU標誌: gaussian + otsu

高斯模糊+自適應閾值: gaussian + adaptive

+0

看看我更新的答案。 – Mahm00d

回答

3

這往往好於之前通過閾值和形態會先用一些降噪技術,如高斯/平均模糊

(代碼在Java中)

Imgproc.cvtColor(inputMat, gMat, Imgproc.COLOR_RGB2GRAY); 
// Gaussian blur : 21x21 window, sigma = 50.0 (select these accordignly) 
Imgproc.GaussianBlur(gMat, gMat, new Size(21.0, 21.0), 50.0); 
// Otsu thresholding (or any other thresholding techinique...) 
Imgproc.threshold(gMat, gMat, 0, 255, Imgproc.THRESH_OTSU | Imgproc.THRESH_BINARY); 

你的輸出:

enter image description here

以上代碼的輸出:

enter image description here


更新:

這些問題往往需要一些上場與參數值來獲得股份公司ood結果並達到最佳值。在第二圖像的情況下,這裏是我使用的代碼(自適應閾值),以獲得更好的結果:

Imgproc.GaussianBlur(inImg, inImg, new Size(21.0, 21.0), 50.0); 
Imgproc.adaptiveThreshold(inImg, inImg, 255, Imgproc.ADAPTIVE_THRESH_MEAN_C, Imgproc.THRESH_BINARY, 111, -20); 

結果:

enter image description here

當然,它並不完美,但在至少反射被刪除。此外,形態學過程可以幫助產生更好的結果。

+0

看看結果 – U23r

2

一種解決方案是應用膨脹和腐蝕,發現比X-像素較小的所有輪廓,並填寫他們用白色:

int main() 
{ 
    // Load the image as a Grayscale 
    Mat image = imread("image.jpg", CV_LOAD_IMAGE_GRAYSCALE); 
    // Threshold the image 
    image = image > 120; 
    // Create bigger image with image width and height + 10 pixels 
    Mat image_big = Mat::zeros(image.size().height + 10, image.size().width + 10, CV_8UC1); 
    // Set bigger image to be all white 
    image_big.setTo(255); 

    Mat image_big_copy; 

    // This may vary, you must find it for yourself 
    // Dilate image 4 times and erode once 
    dilate(image, image, Mat(), Point(-1,-1), 4); 
    erode(image, image, Mat(), Point(-1,-1)); 

    // Copy image in the center of bigger image so you left 5px around image blank/white 
    // Create a new ROI that points to center of the bigger image 
    Mat image_big_roi = image_big(Rect(Point(5, 5), Size(image.size()))); 
    // Copy image to the bigger image ROI 
    addWeighted(image_big_roi, 0., image, 1., 0., image_big_roi); 

    // Create a data copy of image_big 
    image_big.copyTo(image_big_copy); 

    // Find all contours in a given image and store them in contours 
    vector<vector<Point> > contours; 
    findContours(image_big_copy, contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE); 

    for(int i = 0; i < contours.size(); i++) 
    { 
     // This is your condition to filter out unwanted contours etc. 
     // For every contour if its area is bigger/smaller than the sum of pixels 
     if (fabs(contourArea(Mat(contours[i]))) < 800) 
     { 
      // Fill a contour with white color 
      drawContours(image_big, contours, i, Scalar(255), CV_FILLED); 
     } 
    } 

    imshow("Image original", image); 
    imshow("Image edited", image_big); 
    waitKey(0); 

    return 0; 
} 

原圖:

enter image description here

後:

enter image description here