web-dev-qa-db-fra.com

Suppression du filigrane d'une image à l'aide d'OpenCV

Tout d'abord, j'ai cette image et je veux créer une application capable de détecter des images comme celle-ci et d'en supprimer le cercle (filigrane).

image has a watermark

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);
}

Jusqu'à présent, ce que j'ai fait est:

  1. Je le convertis en niveaux de gris
  2. Je détecte le plus grand cercle à l'aide de cercles bruts, puis je crée un cercle de même rayon dans une nouvelle image
  3. Ce nouveau cercle avec celui en niveaux de gris utilisant (bitwise_and) donnez-moi une image avec seulement ce cercle
  4. Seuil cette nouvelle image
  5. bitwise_or le résultat du seuil

Mon problème est qu'aucun texte noir sur la ligne blanche courbe à l'intérieur de ce cercle n'apparaît. J'ai essayé de supprimer la couleur en utilisant les valeurs en pixels au lieu du seuil, mais le problème est le même, donc des solutions ou des suggestions?

Ce sont les résultats: enter image description here

50
Ahmed Ramzy

Je ne sais pas si la solution suivante est acceptable dans votre cas. Mais je pense qu'il fonctionne légèrement mieux et ne se soucie pas de la forme du filigrane.

  • Supprimez les traits à l'aide du filtrage morphologique. Cela devrait vous donner une image de fond. background

  • Calculez l'image de la différence: différence = arrière-plan - initiale, et limitez-la: binaire = seuil (différence)

binary1

  • Seuil l'image de fond et extraire la zone sombre couverte par le filigrane

dark

  • À partir de l'image initiale, extrayez les pixels dans la région du filigrane et limitez ces pixels, puis collez-les dans l'image binaire précédente

binary2

Ci-dessus est une description approximative. Le code ci-dessous devrait mieux l'expliquer.

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++];
        }
    }
}
39
dhanushka