生成step文件_利用opencv给彦女王生成一副蒙太奇画像
大家好呀,前兩天烈陽天道1上映了,不知道大家看沒看呢,里面還有一小段彥穿越蟲洞與猴哥相遇的畫面,彥女王啊啊啊~~
所以我去網上爬了二百來張我大學的風景畫,然后找了以前存的彥女王的圖片,生成了一幅蒙太奇畫像。然后我兩個熱愛的就合體啦!
先看一下什么是蒙太奇圖像吧,其實你肯定見過,只不過不知道叫蒙太奇而已:
一張大的圖片,是由很多小的圖片拼接而成的這種,就是蒙太奇圖像啦(或者叫馬賽克拼圖),我要做的就是把我大學的風景圖拼成彥的圖片。
綜述實現思路
文末附有python代碼,本文為我寫的C++代碼1:讀取文件夾內的風景圖片集,將每張剪裁到90*45大小并存入Mat容器內
2:將圖片模板(彥的照片)擴大為1600*2700大小
3:計算圖片集的直方圖并將結果存到MatND容器內(直方圖容器)
4:雙重for循環以90*45的步長遍歷圖片模板計算各個區域的直方圖,并將區域直方圖與圖片集的直方圖進行比對,得到相似度最高的風景圖片,將該風景圖片替換模板對應區域
5:將4步得到的蒙太奇圖與原模板圖線性相加,得到更為逼真的效果
是不是很簡單的過程?但就這么個過程,我調了一天的bug,然后被迫深入理解了C++的動態回收機制... ... 建議感興趣的小伙伴自己實現一下。
以下代碼在主函數內順次復制粘貼即可1:讀取圖片集并預處理
//【1】圖片集的采集與處理 int Images_number = 256;//圖片集中圖片的數量 int step_x = 80; //將圖片剪裁為80*45大小 int step_y = 45;Mat srcImage; vector<Mat> load_Images;//圖片集容器 char filename[30];//存儲圖片名字 for (int i = 0; i < Images_number; i++) {Mat dstImage;sprintf_s(filename, "./風景圖/ysu (%d).jpg", i);cout << filename << endl;srcImage = imread(filename); //Mat類圖像resize(srcImage, dstImage, Size(step_x, step_y), 0, 0, INTER_NEAREST);load_Images.push_back(dstImage); } cout << "圖片加載完畢" << endl;主要用到了利用sprintf函數得到圖片集有規律的命名,然后for循環依次將imread到的圖片push_back添加到Mat容器內就可以了。
二百多張圖片如何快速整齊的命名,,,看鏈接。
https://jingyan.baidu.com/article/b87fe19e4834a95218356814.html2:調整原模板圖的尺寸大小
//【2】將原模板圖擴大到合適尺寸 Mat originalImage, showImage; originalImage = imread("彥.jpg"); imshow("彥", originalImage); resize(originalImage, showImage, Size(1600, 2700));沒啥好說的,就在基本保持原先長寬比例的條件下,讓長寬都是90*45(圖片集被裁剪的大小)的整數倍就好了。
3:計算圖片集直方圖
//【3】計算圖片集的直方圖 int width = showImage.cols; //模板圖的長寬 int height = showImage.rows; Mat frame; vector<MatND> hsit_list;//直方圖容器 //計算直方圖的參數準備 int bins = 128; //直條數 int hist_sizes[] = { bins,bins,bins }; //存放每個維度的直方圖尺寸數組 // 均為256條寬度 float range[] = { 0,256 }; //每一維數組的取值范圍 // 均為0-255高度 const float* ranges[] = { range,range,range }; int channels[] = { 0,1,2 }; //for循環計算圖片集的直方圖并存儲 for (int i = 0; i < Images_number; i++) {/*load_Images[i].copyTo(frame);*/MatND hsit_RGB;Mat frame;load_Images[i].copyTo(frame);calcHist(&frame, 1, channels, Mat(), hsit_RGB, 3, hist_sizes, ranges, true, false);hsit_list.push_back(hsit_RGB); }和第一步套路類似,循環計算了圖片集所有圖的直方圖并存儲到了一個直方圖容器內。
4:遍歷彥模板圖,計算每一小塊的直方圖并對比,替換
//【4】遍歷,尋找最匹配的圖片并替換 int number_order; for (int x = 0; x < height; x = x + step_y) {for (int y = 0; y < width; y = y + step_x) {Mat roiImage = montageImage(Rect(y, x, step_x, step_y));//Rect(y, x, step_x, step_y)//參數準備MatND hsit_roi;double match_ = 0.0;//匹配度calcHist(&roiImage, 1, channels, Mat(), hsit_roi, 3, hist_sizes, ranges, true, false);for (int i = 0; i < Images_number; i++) {double match;match = compareHist(hsit_roi, hsit_list[i], HISTCMP_CORREL);if (match > match_) {//尋找對比對最高的number_order = i;match_ = match;}}load_Images[number_order].copyTo(roiImage);} } cout << "【4】遍歷,尋找最匹配的圖片并替換成功" << endl;首先兩個步長分別為step_y和step_x的循環是遍歷原圖模板各個小塊區域,并計算該塊的直方圖。
之后用一個for循環在第三步得到的直方圖容器內,尋找與該塊直方圖匹配度最高的風景圖片,然后將該風景圖片替換原圖對應區域。
到此運行完畢我們就可以得到一個不太完美的蒙太奇圖片了:
雖然有些粗糙,但已經可以看出來了叭!效果可以調節裁剪的大小或者原圖模板的大小來改善。但以我代碼設置的參數,執行完都要好幾分鐘,如果有什么優化建議可以交流哈。
來看看女王的腿!
嗯,,竟然是用碑組成的。
我們還可以通過第五步,將上圖左圖與右圖加權得到更為逼真的蒙太奇畫像。
5:將效果圖與原圖加和
Mat dstImage; addWeighted(showImage, 0.4, montageImage, 0.6, 0, dstImage); imwrite("結果圖.jpg", dstImage); imwrite("show.jpg", montageImage);加和后的效果圖:
效果是不是好一些了?可以更改參數使效果更好。由于我還有毛概論文沒寫,就不瞎搞了~
THE END
本文靈感來自知乎@三木青年,代碼都是我自己敲的,網上關于蒙太奇的大概只有我用的C++了,python代碼可以看知乎鏈接:
https://zhuanlan.zhihu.com/p/168667043這么好的一篇文,能不能求個贊呢?
總結
以上是生活随笔為你收集整理的生成step文件_利用opencv给彦女王生成一副蒙太奇画像的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CNN+RNN
- 下一篇: 递归过程中语句执行顺序