C++ OpenCV實(shí)現(xiàn)圖像去水印功能
前言
本文將使用OpenCV C++ 進(jìn)行簡(jiǎn)單圖像水印去除。我們?cè)诰W(wǎng)上download圖片時(shí),經(jīng)常因?yàn)榘鏅?quán)問(wèn)題有水印。本案例通過(guò)編寫算法進(jìn)行簡(jiǎn)單水印去除。
一、水印定位
如圖所示,圖像左下角、右下角有水印。第一步,我們首先得定位水印所在位置。
Mat gray; cvtColor(src, gray, COLOR_BGR2GRAY); //圖像二值化,篩選出白色區(qū)域部分 Mat thresh; threshold(gray, thresh, 220, 255, THRESH_BINARY);
如圖為二值化后得到的效果圖。接下來(lái),我們需要提取水印區(qū)域的像素。
//提取圖片下方的水印,制作掩模圖像 ?? ?Mat mask = Mat::zeros(src.size(), CV_8U); ?? ?int height = src.rows; ?? ?int width = src.cols; ?? ?int start = 0.9*height; ?? ?//遍歷圖像像素,提取出水印部分像素,制作掩模圖像 ?? ?for (int i = start; i < height; i++) ?? ?{ ?? ??? ?uchar*data = thresh.ptr<uchar>(i); ?? ??? ?for (int j = 0; j < width; j++) ?? ??? ?{ ?? ??? ??? ?if (data[j] == 255) ?? ??? ??? ?{ ?? ??? ??? ??? ?mask.at<uchar>(i, j) = 255;?? ??? ??? ? ?? ??? ??? ?}?? ??? ??? ? ?? ??? ?} ?? ?}
如圖所示,至此我們已經(jīng)得到水印部分的二值掩模圖像。接下來(lái),使用OpenCV 內(nèi)置inpaint API進(jìn)行圖像像素修復(fù)。具體可以參考OpenCV C++案例實(shí)戰(zhàn)十四《圖像修復(fù)》
二、圖像修復(fù)
//使用inpaint進(jìn)行圖像修復(fù) Mat result; inpaint(src, mask, result, 1, INPAINT_NS);
如圖所示,這是直接使用提取出的二值掩模進(jìn)行圖像修復(fù)得到的結(jié)果,可以看出效果不是很好。原因是,提取出來(lái)的掩模未能覆蓋完全待修復(fù)像素。故我們需要將掩模圖像進(jìn)行膨脹操作,擴(kuò)大掩模范圍。
//將掩模進(jìn)行膨脹,使其能夠覆蓋圖像更大區(qū)域 Mat kernel = getStructuringElement(MORPH_RECT, Size(5, 5)); dilate(mask, mask, kernel);
如圖為進(jìn)行膨脹過(guò)后的掩模圖像。這時(shí),我們使用這張掩模圖像再進(jìn)行圖像修復(fù)工作,得到效果如圖所示。
三、效果顯示
四、源碼
#include<iostream> #include<opencv2/opencv.hpp> using namespace std; using namespace cv; /* void inpaint( ?? ??? ?InputArray src, ? 原圖 ?? ??? ?InputArray inpaintMask, 二進(jìn)制掩模,指示要修復(fù)的像素 ?? ??? ?OutputArray dst, ?目標(biāo)圖像 ?? ??? ?double inpaintRadius, 像素周圍的鄰域補(bǔ)繪。通常,如果要修復(fù)的區(qū)域很小,則使用較小的值僅產(chǎn)生較少模糊 ?? ??? ?int flags ? ? INPAINT_NS ?或 INPAINT_TELEA ?? ??? ?) */ /* 圖像簡(jiǎn)單水印去除:定位到水印所在位置,將水印部分提取出來(lái)制作二進(jìn)制掩模圖像,使用inpaint API進(jìn)行圖像修復(fù) */ int main() { ?? ?Mat src = imread("test.jpg"); ?? ?if (src.empty()) ?? ?{ ?? ??? ?cout << "No Image!" << endl; ?? ??? ?system("pause"); ?? ??? ?return -1; ?? ?} ?? ?Mat gray; ?? ?cvtColor(src, gray, COLOR_BGR2GRAY); ?? ?//圖像二值化,篩選出白色區(qū)域部分 ?? ?Mat thresh; ?? ?threshold(gray, thresh, 220, 255, THRESH_BINARY); ?? ?//提取圖片下方的水印,制作掩模圖像 ?? ?Mat mask = Mat::zeros(src.size(), CV_8U); ?? ?int height = src.rows; ?? ?int width = src.cols; ?? ?int start = 0.9*height; ?? ?//遍歷圖像像素,提取出水印部分像素,制作掩模圖像 ?? ?for (int i = start; i < height; i++) ?? ?{ ?? ??? ?uchar*data = thresh.ptr<uchar>(i); ?? ??? ?for (int j = 0; j < width; j++) ?? ??? ?{ ?? ??? ??? ?if (data[j] == 255) ?? ??? ??? ?{ ?? ??? ??? ??? ?mask.at<uchar>(i, j) = 255;?? ??? ??? ? ?? ??? ??? ?}?? ??? ??? ? ?? ??? ?} ?? ?} ?? ?//將掩模進(jìn)行膨脹,使其能夠覆蓋圖像更大區(qū)域 ?? ?Mat kernel = getStructuringElement(MORPH_RECT, Size(5, 5)); ?? ?dilate(mask, mask, kernel); ?? ?//使用inpaint進(jìn)行圖像修復(fù) ?? ?Mat result; ?? ?inpaint(src, mask, result, 1, INPAINT_NS); ?? ?imshow("mask", mask); ?? ?imshow("test", result); ?? ?waitKey(0); ?? ?system("pause"); ?? ?return 0; }
總結(jié)
本文使用OpenCV C++ 進(jìn)行簡(jiǎn)單圖像水印去除,關(guān)鍵步驟有以下幾點(diǎn)。
1、定位水印位置,制作二值掩模圖像。
2、進(jìn)行圖像像素修復(fù)。
到此這篇關(guān)于C++ OpenCV實(shí)現(xiàn)圖像去水印功能的文章就介紹到這了,更多相關(guān)C++ OpenCV圖像去水印內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
STL區(qū)間成員函數(shù)及區(qū)間算法總結(jié)
這篇文章主要匯總介紹了STL區(qū)間成員函數(shù)及區(qū)間算法,有需要的小伙伴可以參考下。2015-07-07c語(yǔ)言實(shí)現(xiàn)MD5算法的項(xiàng)目實(shí)踐
MD5用于確保信息傳輸完整一致,是計(jì)算機(jī)廣泛使用的雜湊算法之一,本文主要介紹了c語(yǔ)言實(shí)現(xiàn)MD5算法,具有一定的參考價(jià)值,感興趣的可以了解一下2023-08-08淺談關(guān)于指針作為參數(shù)并改變它的值的問(wèn)題
這篇文章介紹了關(guān)于指針作為參數(shù)并改變它的值的問(wèn)題,有需要的朋友可以參考一下2013-10-10C語(yǔ)言指針學(xué)習(xí)經(jīng)驗(yàn)總結(jié)淺談
指針是C語(yǔ)言的難點(diǎn)和重點(diǎn),但指針也是C語(yǔ)言的靈魂 。2013-03-03Qt項(xiàng)目實(shí)戰(zhàn)之實(shí)現(xiàn)多文本編輯器
這篇文章主要為大家詳細(xì)介紹了如何利用Qt實(shí)現(xiàn)簡(jiǎn)易的多文本編輯器,文中的示例代碼講解詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴可以了解一下2023-03-03C語(yǔ)言實(shí)現(xiàn)選擇排序、直接插入排序、冒泡排序的示例
這篇文章主要介紹了C++實(shí)現(xiàn)選擇排序、直接插入排序、冒泡排序的代碼示例,相當(dāng)簡(jiǎn)潔直觀,也是算法和數(shù)據(jù)結(jié)構(gòu)學(xué)習(xí)中的基礎(chǔ),需要的朋友可以參考下2016-02-02