Seam Carving

 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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值