OpenCV C++案例十六,哈哈鏡圖像及去水印
關(guān)注濤濤CV,設(shè)置星標(biāo),更新不錯(cuò)過(guò)
作者Zero___Chen
來(lái)源blog.csdn.net/Zero___Chen
本文將使用OpenCV C++ 制作哈哈鏡圖像。
其實(shí)原理很簡(jiǎn)單,就是讓圖像像素扭曲,將像素重新進(jìn)行映射。
假設(shè)輸入圖像寬w,高h(yuǎn)。圖像中心點(diǎn)坐標(biāo)(cx,cy),圖像任意像素點(diǎn)(x,y)到中心點(diǎn)距離 dx=(x-cx),dy=(y-cy),變換半徑r。
一、凸透鏡

制作凸透鏡效果(將圖像放大)。根據(jù)網(wǎng)上查找的變換公式:
圖像放大:凸透鏡x = (dx / 2)*(sqrt(pow(dx, 2) + pow(dy, 2)) / r) + cx;y = (dy / 2)*(sqrt(pow(dx, 2) + pow(dy, 2)) / r) + cy;
1.功能源碼
請(qǐng)查看源碼注釋
bool Mirror_Magnify(Mat src){/*圖像放大:凸透鏡x = (dx / 2)*(sqrt(pow(dx, 2) + pow(dy, 2)) / r) + cx;y = (dy / 2)*(sqrt(pow(dx, 2) + pow(dy, 2)) / r) + cy;*/Mat canvas = Mat::zeros(src.size(), src.type()); //畫(huà)布,重新生成哈哈圖像//圖像中心int cx = src.cols / 2;int cy = src.rows / 2;//決定哈哈鏡大小int radius = 200;//圖像像素修改for (int i = 0; i < src.rows; i++){for (int j = 0; j < src.cols; j++){//任意像素點(diǎn)到圖像中心距離int dx = j - cx;int dy = i - cy;//重新映射像素點(diǎn)位置int x = (dx / 2)*(sqrt(pow(dx, 2) + pow(dy, 2)) / radius) + cx;int y = (dy / 2)*(sqrt(pow(dx, 2) + pow(dy, 2)) / radius) + cy;for (int c = 0; c < 3; c++){//防止越界if ((x > 0 && x < src.cols) && (y > 0 && y < src.rows)){canvas.at(i, j)[c] = src.at(y, x)[c];}}}}imshow("Mirror_Magnify", canvas);return true;}
2.效果顯示

二、凹透鏡
制作凹透鏡效果(將圖像縮?。?。根據(jù)網(wǎng)上查找的變換公式:
圖像縮小:凹透鏡x = sqrt(sqrt(pow(dx, 2) + pow(dy, 2))) * compress * cos(atan2(dy, dx)) + cx;y = sqrt(sqrt(pow(dx, 2) + pow(dy, 2))) * compress * sin(atan2(dy, dx)) + cy;
1.功能源碼
請(qǐng)查看源碼注釋
bool Mirror_Narrow(Mat src){/*圖像縮?。喊纪哥Rx = sqrt(sqrt(pow(dx, 2) + pow(dy, 2))) * compress * cos(atan2(dy, dx)) + cx;y = sqrt(sqrt(pow(dx, 2) + pow(dy, 2))) * compress * sin(atan2(dy, dx)) + cy;*/Mat canvas = Mat::zeros(src.size(), src.type());//畫(huà)布,重新生成哈哈圖像int compress = 12; //壓縮強(qiáng)度//圖像中心int cx = src.cols / 2;int cy = src.rows / 2;//圖像像素修改for (int i = 0; i < src.rows; i++){for (int j = 0; j < src.cols; j++){//任意像素點(diǎn)到圖像中心距離int dx = j - cx;int dy = i - cy;//重新映射像素點(diǎn)位置int x = sqrt(sqrt(pow(dx, 2) + pow(dy, 2))) * compress * cos(atan2(dy, dx)) + cx;int y = sqrt(sqrt(pow(dx, 2) + pow(dy, 2))) * compress * sin(atan2(dy, dx)) + cy;for (int c = 0; c < 3; c++){//防止越界if ((x > 0 && x < src.cols) && (y > 0 && y < src.rows)){canvas.at<Vec3b>(i, j)[c] = src.at<Vec3b>(y, x)[c];}}}}imshow("Mirror_Narrow", canvas);return true;}
2.效果顯示

三、源碼
using namespace std;using namespace cv;/*哈哈鏡實(shí)現(xiàn)原理:讓圖像像素扭曲,將像素重新進(jìn)行映射假設(shè)輸入圖像寬w,高h(yuǎn)。圖像中心點(diǎn)坐標(biāo)(cx,cy),圖像任意像素點(diǎn)(x,y)到中心點(diǎn)距離 dx=(x-cx),dy=(y-cy),變換半徑r*/bool Mirror_Magnify(Mat src){/*圖像放大:凸透鏡x = (dx / 2)*(sqrt(pow(dx, 2) + pow(dy, 2)) / r) + cx;y = (dy / 2)*(sqrt(pow(dx, 2) + pow(dy, 2)) / r) + cy;*/Mat canvas = Mat::zeros(src.size(), src.type()); //畫(huà)布,重新生成哈哈圖像//圖像中心int cx = src.cols / 2;int cy = src.rows / 2;//決定哈哈鏡大小int radius = 200;//圖像像素修改for (int i = 0; i < src.rows; i++){for (int j = 0; j < src.cols; j++){//任意像素點(diǎn)到圖像中心距離int dx = j - cx;int dy = i - cy;//重新映射像素點(diǎn)位置int x = (dx / 2)*(sqrt(pow(dx, 2) + pow(dy, 2)) / radius) + cx;int y = (dy / 2)*(sqrt(pow(dx, 2) + pow(dy, 2)) / radius) + cy;for (int c = 0; c < 3; c++){//防止越界if ((x > 0 && x < src.cols) && (y > 0 && y < src.rows)){canvas.at<Vec3b>(i, j)[c] = src.at<Vec3b>(y, x)[c];}}}}imshow("Mirror_Magnify", canvas);return true;}bool Mirror_Narrow(Mat src){/*圖像縮小:凹透鏡x = sqrt(sqrt(pow(dx, 2) + pow(dy, 2))) * compress * cos(atan2(dy, dx)) + cx;y = sqrt(sqrt(pow(dx, 2) + pow(dy, 2))) * compress * sin(atan2(dy, dx)) + cy;*/Mat canvas = Mat::zeros(src.size(), src.type());//畫(huà)布,重新生成哈哈圖像int compress = 12; //壓縮強(qiáng)度//圖像中心int cx = src.cols / 2;int cy = src.rows / 2;//圖像像素修改for (int i = 0; i < src.rows; i++){for (int j = 0; j < src.cols; j++){//任意像素點(diǎn)到圖像中心距離int dx = j - cx;int dy = i - cy;//重新映射像素點(diǎn)位置int x = sqrt(sqrt(pow(dx, 2) + pow(dy, 2))) * compress * cos(atan2(dy, dx)) + cx;int y = sqrt(sqrt(pow(dx, 2) + pow(dy, 2))) * compress * sin(atan2(dy, dx)) + cy;for (int c = 0; c < 3; c++){//防止越界if ((x > 0 && x < src.cols) && (y > 0 && y < src.rows)){canvas.at<Vec3b>(i, j)[c] = src.at<Vec3b>(y, x)[c];}}}}imshow("Mirror_Narrow", canvas);return true;}int main(){Mat src = imread("test.jpg");if (src.empty()){cout << "No Image!" << endl;system("pause");return -1;}Mirror_Magnify(src);Mirror_Narrow(src);imshow("test", src);waitKey(0);system("pause");;return 0;}
總結(jié)
本文使用OpenCV C++ 制作哈哈鏡圖像,關(guān)鍵步驟有以下幾點(diǎn)。
1、了解哈哈鏡圖像制作原理:根據(jù)公式對(duì)圖像像素進(jìn)行重新映射。
本文將使用OpenCV C++ 進(jìn)行簡(jiǎn)單圖像水印去除。
我們?cè)诰W(wǎng)上download圖片時(shí),經(jīng)常因?yàn)榘鏅?quán)問(wèn)題有水印。本案例通過(guò)編寫(xiě)算法進(jìn)行簡(jiǎn)單水印去除。
一、水印定位

如圖所示,圖像左下角、右下角有水印。第一步,我們首先得定位水印所在位置。
Mat gray;cvtColor(src, gray, COLOR_BGR2GRAY);//圖像二值化,篩選出白色區(qū)域部分Mat thresh;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(i);for (int j = 0; j < width; j++){if (data[j] == 255){mask.at(i, j) = 255;}}}

如圖所示,至此我們已經(jīng)得到水印部分的二值掩模圖像。接下來(lái),使用OpenCV 內(nèi)置inpaint API進(jì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ù)工作,得到效果如圖所示。

三、效果顯示

四、源碼
using namespace std;using namespace cv;/*void inpaint(InputArray src, 原圖InputArray inpaintMask, 二進(jìn)制掩模,指示要修復(fù)的像素OutputArray dst, 目標(biāo)圖像double inpaintRadius, 像素周?chē)泥徲蜓a(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ù)。
總結(jié):
10年機(jī)器視覺(jué)網(wǎng)站,5年人工智能網(wǎng)站
2019經(jīng)歷總結(jié),2018視覺(jué)總結(jié)
項(xiàng)目感悟,賺錢(qián)思路,項(xiàng)目視頻
課程:
《機(jī)器視覺(jué):應(yīng)用講解》,一總體概述,二相機(jī)篇,三鏡頭篇,四光源篇,五光學(xué)系統(tǒng)選型,六視覺(jué)開(kāi)發(fā)軟件,七相機(jī)標(biāo)定技術(shù),八項(xiàng)目案例解析,九視覺(jué)公司分析,十產(chǎn)業(yè)發(fā)展情況
筆記:
《智能革命》《人工智能》《AI?未來(lái)》《好好賺錢(qián)》《韭菜的自我修養(yǎng)》讀書(shū)筆記
行業(yè):
服務(wù)機(jī)器人公司,機(jī)器視覺(jué)公司,自動(dòng)駕駛公司,ADAS公司總結(jié), 防疫機(jī)器人發(fā)展,騰訊未來(lái)交通
SLAM:
Vslam方案+源碼,語(yǔ)義SLAM與深度相機(jī),SLAM和導(dǎo)航避障,視覺(jué)SLAM總結(jié)
秦學(xué)英《三維物體的識(shí)別與跟蹤》,章國(guó)鋒《視覺(jué)SLAM》,申抒含《基于圖像的三維建?!?/a>,姜翰青《RGB -D SLAM》記錄筆記
機(jī)器視覺(jué):
毫米波雷達(dá),雷達(dá)視覺(jué)融合,2021視覺(jué)研討會(huì),2020上海研討會(huì),雙目和激光的三維重建,2021視覺(jué)市場(chǎng)研究,太陽(yáng)能行業(yè)應(yīng)用
機(jī)器視覺(jué)基本概念筆記,記錄五,記錄四,記錄三,記錄二,記錄一
圖像處理:
圖像處理基本概念筆記,記錄八,記錄七,記錄六 ,記錄五,記錄四 ,記錄三,記錄二 ,記錄二,記錄一
歡迎支持,點(diǎn)擊在看,分享
