Seam Carving

来源:互联网 发布:华杉孙子兵法知乎 编辑:程序博客网 时间:2024/06/05 17:49
 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;}

原论文地址:http://dl.acm.org/citation.cfm?id=1276390

1 0