3月20日,我们的第二次英才计划活动,又来到了南开大学津南校区,先是说了下上回布置的阅读论文的作业情况,然后给我们简单讲解了下这个论文的算法,之后下午的时间便是我们上机实践了。
下午的时候,程老师又给我们指点了一下,程序运行成功了,可是结果没有预想的效果,于是我在回家后的下一周末,花了一个小时,又将其改对了,十分高兴。!
这个程序的大致意思呢就是在平常缩放图片时会造成比例失真,而这个程序通过动态规划选择几条"最不重要"的像素的路径,删除,再将图片输出,以达到效果。
下面这个我写的程序中对于"最不重要"仅仅是通过计算某一位置的重要度=abs(上面像素的像素值-自己的) + abs (右面像素的像素值-自己的)得到,还有其他更为精确的方法,但此法较简单,因此使用了此法。 另外本题还可通过链表实现来代替每次的for循环重复计算重要度值,来提高程序运行速度。
不过还是要庆贺自己写的第一个opencv的较大程序。
更多的方法详见文章末尾原文地址。
// SeamCarving.cpp : 定义控制台应用程序的入口点。
//
#pragma warning(disable:4819)
#include "stdafx.h"
#include "cstdio"
#include <cmath>
#include <opencv2/opencv.hpp>
#define CV_VERSION_ID CVAUX_STR(CV_MAJOR_VERSION) CVAUX_STR(CV_MINOR_VERSION) CVAUX_STR(CV_SUBMINOR_VERSION)
#define cvLIB(name) lnkLIB("opencv_" name CV_VERSION_ID)
//#pragma comment( lib, cvLIB("world"))
#pragma comment(lib, "opencv_world310d.lib")
using namespace cv;
using namespace std;
const int Number = 6000;
int pixel[Number][Number], s[Number][Number], E[Number][Number], ss[Number][Number];
int rowNumber, colNumber;
Mat dst;
void solvepixel(Mat& srcpic, Mat& dst)
{
//转化为灰度图
cvtColor(srcpic, dst, CV_RGB2GRAY);
//遍历像素
rowNumber = dst.rows;
colNumber = dst.cols;
for (int i = 0; i < rowNumber; i++)
{
uchar* data = dst.ptr<uchar>(i);
for (int j = 0; j < colNumber; j++)
pixel[i][j] = (int)data[j];
}
}
int pickmin(int a, int b, int c,int flag)
{
if (flag == 0)
if (b < c) return flag;
else return flag + 1;
else if (flag == rowNumber - 1)
if (a < b) return flag - 1;
else return flag;
else
{
int abc = min(min(a, b), c);
if (abc == a) return flag - 1;
if (abc == b) return flag;
if (abc == c) return flag + 1;
}
}
Mat solve(Mat& srcpic)
{
//读入像素并存入pixel数组中
solvepixel(srcpic, dst);
//计算s值存入s数组
for (int i = 1; i < rowNumber; i++)
for (int j = 0; j < colNumber; j++)
s[i][j] = abs(pixel[i][j + 1] - pixel[i][j]) + abs(pixel[i - 1][j] - pixel[i][j]);
for (int j = 0; j < colNumber; j++) E[0][j] = s[0][j];
for (int i = 1; i < rowNumber; i++)
for (int j = 0; j < colNumber; j++)
{
if (j != 0 && j != colNumber - 1)
E[i][j] = s[i][j] + min(min(E[i - 1][j - 1], E[i - 1][j]), E[i - 1][j + 1]);
else if (j == 0)
E[i][j] = s[i][j] + min(E[i - 1][j + 1], E[i - 1][j]);
else E[i][j] = s[i][j] + min(E[i - 1][j - 1], E[i - 1][j]);
}
int flag = 0;
for (int j = 0; j < colNumber - 1; j++)
if (E[rowNumber - 1][j] < E[rowNumber - 1][flag] && E[rowNumber - 1][j] > 0) flag = j;
for (int i = rowNumber - 1; i > 0; i--)
{
E[i][flag] = 0;
flag = pickmin(E[i - 1][flag - 1], E[i - 1][flag], E[i - 1][flag + 1], flag);
}
for (int i = 0; i < rowNumber; i++)
for (int j = 0, m = 0; j < colNumber; j++)
{
if (E[i][j] == 0) {
s[i][j] = 0; continue;
}
else if (s[i][j] == 0) continue;
else ss[i][m++] = s[i][j];
}
colNumber--;
Mat picture(rowNumber, colNumber, CV_8UC3);
for (int i = 0; i < rowNumber; i++) {
Vec3b* dst = picture.ptr<Vec3b>(i);
Vec3b* src = srcpic.ptr<Vec3b>(i);
for (int j = 0, k = 0; j < colNumber; j++) {
if (E[i][j] == 0)
continue;
dst[k] = src[j];
k++;
}
}
return picture;
}
int main()
{
Mat srcpic = imread("srcpic.jpg");
resize(srcpic, srcpic, Size(), 0.4, 0.4);//将某些较大的在屏幕上无法显示的图片缩小
imshow("sourcepicture", srcpic);
for (int k = 0; k < 100; k++)
{
srcpic = solve(srcpic);
}
imshow("afterchange",srcpic);
waitKey(0);
return 0;
}