AnswerOpenCV(0416)一週佳作欣賞

2017年4月16日 一週AnswerOpenCV佳作賞析

1、Hello How to smooth edge of text in binary image, based on threshold.Something like anti-aliasing by openCv? example

 

 

題目:圖片去毛刺

優質解答:

#include <iostream>
#include "opencv2/opencv.hpp"
using namespace cv;
using namespace std;
bool SmoothEdgeSingleChannel( Mat mInput,Mat &mOutput, double amount, double radius, uchar Threshold) ;
bool SmoothEdge( Mat mInput_Bgr,Mat &mOutput_Bgr, double amount, double radius, uchar Threshold) 
{
    if(mInput_Bgr.empty())
    {
        return 0;
    }
    if(radius<1)
        radius=1;
    Mat mInput,mOutput;
    Mat mChannel[3];
    split(mInput_Bgr,mChannel);
    for (int i = 0; i < 3; i++)
    {
        mInput= mChannel[i];
        SmoothEdgeSingleChannel(mInput,mOutput,amount, radius,Threshold); 
        mOutput.copyTo(mChannel[i]);
    }
    merge(mChannel,3,mOutput_Bgr);
    return true;
}
bool SmoothEdgeSingleChannel( Mat mInput,Mat &mOutput, double amount, double radius, uchar Threshold) 
{
    if(mInput.empty())
    {
        return 0;
    }
    if(radius<1)
        radius=1;
    Mat mGSmooth,mDiff,mAbsDiff;
    mOutput = Mat(mInput.size(),mInput.type());
    GaussianBlur(mInput,mGSmooth,Size(0,0),radius); 
    //imshow("mGSmooth",mGSmooth);
    subtract(mGSmooth,mInput,mDiff);
    //imshow("mDiff",mDiff);
    mDiff*=amount;
    threshold(abs(2* mDiff),mAbsDiff,Threshold,255,THRESH_BINARY_INV);
    mDiff.setTo(Scalar(0),mAbsDiff);
    //imshow("mDiff Multiplied",mDiff);
    add(mInput,mDiff,mOutput);
    return true;
}
//Credits: http://stackoverflow.com/questions/34527349/non-connecting-morphological-filter/34535023#34535023
bool SmoothContours(vector<vector<Point>> contours_Src,vector<vector<Point>> &contours_Smooth,int Radius,double Sigma )
{
    if(contours_Src.size()==0)
        return false;
    int FilterSize = 2 * Radius + 1;
    for (int id = 0; id < contours_Src.size(); id++)
    {
        size_t len = contours_Src[id].size() + 2 * Radius;
        size_t idx = (contours_Src[id].size() - Radius);
        vector<float> x, y;
        vector<float> xFilt, yFilt;
        vector<Point> contours_Smooth_Curr;
        for (size_t i = 0; i < len; i++)
        {
            x.push_back(contours_Src[id][(idx + i) % contours_Src[id].size()].x);
            y.push_back(contours_Src[id][(idx + i) % contours_Src[id].size()].y);
        }
        GaussianBlur(x, xFilt, Size(FilterSize, FilterSize), Sigma, Sigma);
        GaussianBlur(y, yFilt, Size(FilterSize, FilterSize), Sigma, Sigma);
        for (size_t i = Radius; i < contours_Src[id].size() + Radius; i++)
        {
            contours_Smooth_Curr.push_back(Point(xFilt[i], yFilt[i]));
        }
        contours_Smooth.push_back(contours_Smooth_Curr);
    }
    return true;
}
int main(int argc, char* argv[])
{
    string FileName_S="e:/template/input.png";
    Mat mSource,mThres,mResult,mSmoothEdge;
    mSource= imread(FileName_S,0);
    RNG rng(12345);
    if(mSource.empty())
    {
        cout<<"[Error] Invalid Input Image!";
        return 0;
    }
    mSmoothEdge= mSource.clone();
    mSmoothEdge.setTo(0);
    threshold(mSource,mThres,125,255,THRESH_BINARY_INV);
    imshow("Source mThres",mThres);
    cvtColor(mSource,mResult,COLOR_GRAY2BGR);
    vector<vector<Point>> contours;
    vector<Vec4i> hierarchy;
    vector<vector<Point>> contours_Smoothed;
    int Radius=1;
    double Sigma=2.0;
    findContours( mThres.clone(), contours, hierarchy, RETR_TREE, CV_CHAIN_APPROX_SIMPLE );
    //Smoothing Contour Points using Gaussian Smooth!
    SmoothContours(contours,contours_Smoothed,Radius,Sigma);
    for( size_t i = 0; i< contours.size(); i++ )
    {
        /*Scalar color = Scalar( rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255) );
        drawContours( mResult, contours, (int)i, color, 1, 8, vector<Vec4i>(), 0, Point() );*/
        if(hierarchy[i][2]<0)//These are inner most child contours
        {
            drawContours( mSmoothEdge, contours_Smoothed, i, Scalar(0), -1, 8, vector<Vec4i>(), 0, Point() );
        }
        if(hierarchy[i][3]<0)//These are outer most parent contours
        {
            drawContours( mSmoothEdge, contours_Smoothed, i, Scalar(255), -1, 8, vector<Vec4i>(), 0, Point() );
        }
    }
    //imshow("Source Image",mResult);
    imshow("1) Smooth Edge Points",mSmoothEdge);
 
    //Smoothing Edge using Modified Unsharp Masking
    mSmoothEdge.setTo(0);
    SmoothEdgeSingleChannel(mThres,mSmoothEdge,2.5,1.0,254);
    imshow("2) Smooth Edges",mSmoothEdge);
 
    waitKey();
}

 

 

 

解析:

這個效果是不錯的,但是廢話太多了;精華部分值得體會。注意在做“邊界獲得”運算後,適當放大後加回了原始圖像。

#include "stdafx.h"
#include <iostream>
#include "opencv2/opencv.hpp"
using namespace cv;
using namespace std;
bool SmoothEdgeSingleChannel( Mat mInput,Mat &mOutput, double amount, double radius, uchar Threshold) 
{
    if(mInput.empty())
    {
        return 0;
    }
    if(radius<1)
        radius=1;
    Mat mGSmooth,mDiff,mAbsDiff;
    mOutput = Mat(mInput.size(),mInput.type());
    GaussianBlur(mInput,mGSmooth,Size(0,0),radius); 
    //imshow("mGSmooth",mGSmooth);
    subtract(mGSmooth,mInput,mDiff);
    //imshow("mDiff",mDiff);
    mDiff*=amount;
    threshold(abs(2* mDiff),mAbsDiff,Threshold,255,THRESH_BINARY_INV);
    mDiff.setTo(Scalar(0),mAbsDiff);
    //imshow("mDiff Multiplied",mDiff);
    add(mInput,mDiff,mOutput);
    return true;
}
int main(int argc, char* argv[])
{
    string FileName_S="e:/template/input.png";
    Mat src = imread(FileName_S,0);
    Mat dst;
    imshow("src",src);
    bitwise_not(src,src);
    SmoothEdgeSingleChannel(src,dst,2.5,1.0,254);
    imshow("dst",dst);
    waitKey();
} 

Hi,

In my project, I apply findcontours function to detect a rectangular object within a region of interest in the image. I am doing it in real time. Subsequently, I enclose the detected contour by a boundedrect which gives me its four vertices. However, the position of these vertices is not stable, it is changing very fast. Looks like the contour area is growing and shrinking, and have variations which causes the vertices' position to change. I have tried following solutions, but to no avail.

  1. Low pass filtering on the output of pixel positions.
  2. Median and Gaussian blur within the ROI.
  3. FastNlmeansDenoising: which is too slow for my application.
//medianBlur(img, img, 21);
   cvtColor (img, img, COLOR_BGR2GRAY);
  //fastNlMeansDenoising (img, img, 3, 7, 21);
  threshold(img, img, 0, 255, CV_THRESH_BINARY_INV | CV_THRESH_OTSU);
  //medianBlur(img, img, 21);
  Mat dilateElement = getStructuringElement( MORPH_RECT,Size(11,11));
 //Mat erodeElement = getStructuringElement ( MORPH_RECT, Size(8,8) );
 dilate(img,img,dilateElement);
 //erode (img, img, erodeElement);
 floodFill (img, Point(0,0), Scalar(0));
 //  namedWindow("dilated",CV_WINDOW_NORMAL);
 //  imshow("dilated",img);
 //  cout << "Inside corrected corners p3" << endl;
 //GaussianBlur (img, img, Size(15,15), 0, 0);
 Canny (img, img, 0, 10, 5);
 dilate(img, img, Mat(), Point(-1,-1));

 //cout << "Inside corrected corners p3.5" << endl;
 findContours(img, contours, CV_RETR_LIST, CV_CHAIN_APPROX_NONE);
 // cout<<contours.size()<<endl;
 //  Mat tempimg(img.rows, img.cols, CV_8U, cv::Scalar(0));
 //  drawContours( tempimg, contours, -1, Scalar(255), 3, CV_AA );
 //  namedWindow("contours", CV_WINDOW_NORMAL);
 //  imshow("contours", tempimg);
 //  cout << "Inside corrected corners p4" << endl;
 

 

這個問題在AnswerOpenCV上也是討論的很激烈,但是大多數還是從去噪音這個思路來說的 。

我認爲在實時項目中(比如android),如果還是用靜態圖片的同樣的處理方法來處理圖片和尋找輪廓,肯定是會出現“顛簸”的情況。因此在考慮單幅圖片的時候,還要同時考慮前面的/後面的圖片;如果轉換,也需要平滑處理。這些應該都是圖像處理以外的東西了。

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章