Usuwanie znaku wodnego z obrazu za pomocą opencv

Przede wszystkim mam ten obraz i chcę zrobić aplikację, która może wykryć takie obrazy i usunąć z niego okrąg (Znak wodny).

obraz ma znak wodny

int main(){
    Mat im1,im2,im3,gray,gray2,result;

    im2=imread(" (2).jpg");
    namedWindow("x",CV_WINDOW_FREERATIO);
    imshow("x",im2);

    //converting it to gray
    cvtColor(im2,gray,CV_BGR2GRAY);
    // creating a new image that will have the cropped ellipse
    Mat ElipseImg(im2.rows,im2.cols,CV_8UC1,Scalar(0,0,0));

    //detecting the largest circle
    GaussianBlur(gray,gray,Size(5,5),0);
    vector<Vec3f> circles;
    HoughCircles(gray,circles,CV_HOUGH_GRADIENT,1,gray.rows/8,100,100,100,0);

    uchar x;
    int measure=0;int id=0;
    for(int i=0;i<circles.size();i++){
        if(cvRound(circles[i][2])>measure && cvRound(circles[i][2])<1000){
            measure=cvRound(circles[i][2]);
            id=i;
        }
    }


    Point center(cvRound(circles[id][0]),cvRound(circles[id][1]));
    int radius=cvRound(circles[id][2]);
    circle(im2,center,3,Scalar(0,255,0),-1,8,0);
    circle(im2,center,radius,Scalar(0,255,0),2,8,0);
    ellipse(ElipseImg,center,Size(radius,radius),0,0,360,Scalar(255,255,255),-1,8);
    cout<<"center: "<<center<<" radius: "<<radius<<endl;



    Mat res;
    bitwise_and(gray,ElipseImg,result);
    namedWindow("bitwise and",CV_WINDOW_FREERATIO);
    imshow("bitwise and",result);

    // trying to estimate the Intensity  of the circle for the thresholding
    x=result.at<uchar>(cvRound(circles[id][0]+30),cvRound(circles[id][1]));
    cout<<(int)x;

    //thresholding the  output image
    threshold(ElipseImg,ElipseImg,(int)x-10,250,CV_THRESH_BINARY);
    namedWindow("threshold",CV_WINDOW_FREERATIO);
    imshow("threshold",ElipseImg);

    // making bitwise_or
    bitwise_or(gray,ElipseImg,res);
    namedWindow("bitwise or",CV_WINDOW_FREERATIO);
    imshow("bitwise or",res);

    waitKey(0);
}

Do tej pory to co zrobiłem to:

  1. konwertuję na skalę szarości
  2. wykrywam największy okrąg za pomocą okręgów hougha, a następnie wykonuję okrąg o tym samym promieniu na nowym obrazku
  3. Ten nowy okrąg z odcieniem szarości używając (bitwise_and) daj mi obrazek z tym tylko koło
  4. Threshold that new image
  5. bitwise_or wynik progu

Mój problem polega na tym, że żaden czarny tekst na zakrzywionej białej linii wewnątrz tego okręgu nie pojawił się. Próbowałem usunąć kolor za pomocą wartości pikseli zamiast progu, ale problem jest taki sam, więc jakieś rozwiązania lub sugestie?

Oto wyniki: Tutaj wpisz opis obrazka

Author: zenzelezz, 2015-08-20

1 answers

Nie jestem pewien, czy poniższe rozwiązanie jest dopuszczalne w Twoim przypadku. Ale myślę, że działa nieco lepiej i nie obchodzi mnie kształt znaku wodnego.

  • Usuń obrysy za pomocą filtrowania morfologicznego. To powinno dać obraz tła. Informacje ogólne

  • Oblicz różnicę image: difference = background-initial, and threshold it: binary = próg (różnica)

binary1

  • próg obraz tła i wyodrębnić ciemny obszar objęty znakiem wodnym

ciemny

  • z obrazu początkowego wyodrębnij piksele w obszarze znaku wodnego i ustaw próg tych pikseli, a następnie wklej je do wcześniejszego obrazu binarnego

binary2

Powyżej jest przybliżony opis. Poniższy kod powinien wyjaśnić to lepiej.

Mat im = [load the color image here];

Mat gr, bg, bw, dark;

cvtColor(im, gr, CV_BGR2GRAY);

// approximate the background
bg = gr.clone();
for (int r = 1; r < 5; r++)
{
    Mat kernel2 = getStructuringElement(MORPH_ELLIPSE, Size(2*r+1, 2*r+1));
    morphologyEx(bg, bg, CV_MOP_CLOSE, kernel2);
    morphologyEx(bg, bg, CV_MOP_OPEN, kernel2);
}

// difference = background - initial
Mat dif = bg - gr;
// threshold the difference image so we get dark letters
threshold(dif, bw, 0, 255, CV_THRESH_BINARY_INV | CV_THRESH_OTSU);
// threshold the background image so we get dark region
threshold(bg, dark, 0, 255, CV_THRESH_BINARY_INV | CV_THRESH_OTSU);

// extract pixels in the dark region
vector<unsigned char> darkpix(countNonZero(dark));
int index = 0;
for (int r = 0; r < dark.rows; r++)
{
    for (int c = 0; c < dark.cols; c++)
    {
        if (dark.at<unsigned char>(r, c))
        {
            darkpix[index++] = gr.at<unsigned char>(r, c);
        }
    }
}
// threshold the dark region so we get the darker pixels inside it
threshold(darkpix, darkpix, 0, 255, CV_THRESH_BINARY | CV_THRESH_OTSU);

// paste the extracted darker pixels
index = 0;
for (int r = 0; r < dark.rows; r++)
{
    for (int c = 0; c < dark.cols; c++)
    {
        if (dark.at<unsigned char>(r, c))
        {
            bw.at<unsigned char>(r, c) = darkpix[index++];
        }
    }
}
 34
Author: dhanushka,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-21 13:02:05