#include <opencv2/core/core.hpp>
#include <opencv2/opencv.hpp>
#include <opencv2/core/core.hpp>
#include <opencv/cv.h>
#include <opencv2/highgui/highgui.hpp>
#include <math.h>
#include <string.h>
#include <opencv/cv.h>
#include <stdio.h>
using namespace cv;
using namespace std;
Mat getTi(Mat &src){
int i, j;
Mat out = Mat::zeros(src.size(), CV_32FC1);
for(i=0;i<src.rows-1;i++){
float *ptr1 = out.ptr<float>(i);
for(j=0;j<src.cols-1;j++){
ptr1[j] = abs(src.at<uchar>(i,j)-src.at<uchar>(i+1,j))+abs(src.at<uchar>(i, j)-src.at<uchar>(i, j+1));
}
ptr1[src.cols-1] = ptr1[src.cols-2];
}
float *ptr1 = out.ptr<float>(src.rows-1);
float *ptr2 = out.ptr<float>(src.rows-2);
for(j=0;j<src.cols;j++){
ptr1[j] = ptr2[j];
}
return out;
}
Mat getEnergy(Mat &srcXY, Mat &tmpCircol){
int i, j;
Mat out;
short k[3];
int index;
srcXY.copyTo(out);
for(i=1;i<srcXY.rows;i++){
/*********第一列*****************/
k[1] =out.at<float>(i-1,0);
k[2] =out.at<float>(i-1,1);
if(k[1]>k[2]){
if(i>0){
out.at<float>(i,0) = srcXY.at<float>(i,0)+out.at<float>(i-1,0);
}else{
out.at<float>(i,0) = srcXY.at<float>(i,0);
}
tmpCircol.at<uchar>(i,0) = 2;
}else{
if(i>0){
out.at<float>(i,0) = srcXY.at<float>(i,0)+out.at<float>(i-1,1);
}else{
out.at<float>(i,0) = srcXY.at<float>(i,0);
}
tmpCircol.at<uchar>(i,0) = 1;
}
/***********中间列***************/
for(j=1;j<srcXY.cols-1;j++){
k[0] =out.at<float>(i-1,j-1);
k[1] =out.at<float>(i-1,j);
k[2] =out.at<float>(i-1,j+1);
index = 0;
if(k[1]<k[0]){
index = 1;
}
if(k[2]<k[index]){
index = 2;
}
out.at<float>(i,j) = srcXY.at<float>(i,j)+out.at<float>(i-1,j+index-1);
tmpCircol.at<uchar>(i,j) = index;
}
/*********最后一列*************/
k[0] =out.at<float>(i-1,srcXY.cols-2);
k[1] =out.at<float>(i-1,srcXY.cols-1);
if(k[0]>k[1]){
out.at<float>(i,srcXY.cols-1) = srcXY.at<float>(i,srcXY.cols-1)+out.at<float>(i-1,srcXY.cols-1);
tmpCircol.at<uchar>(i, srcXY.cols-1) = 1;
}else{
out.at<float>(i,srcXY.cols-1) = srcXY.at<float>(i,srcXY.cols-1)+out.at<float>(i-1,srcXY.cols-2);
tmpCircol.at<uchar>(i, srcXY.cols-1) = 0;
}
}
return out;
}
void getCircolAddr(Mat &srcEnergy, Mat &tmpCircol, int *cirColAddr){
int i, j, index=0;
float tmpEnergyValue;
float *ptr1 = srcEnergy.ptr<float>(srcEnergy.rows-1);
tmpEnergyValue = ptr1[0];
for(i=1;i<srcEnergy.cols;i++){
if(ptr1[i]<tmpEnergyValue){
index = i;
tmpEnergyValue = ptr1[i];
}
}
for(i=srcEnergy.rows-1;i>=0;i--){
cirColAddr[i] = index;
index = index+tmpCircol.at<uchar>(i,index)-1;
}
}
Mat getResultPic(Mat &src, float scale){
int i, j, k;
int circRow = src.rows - src.rows/scale;
int circCol = src.cols - src.cols/scale;
int cirColAddr[src.rows];
short tmpTi = 0;
int leftThre, rightThre, midThre;
Mat tmp = src;
Mat out, srcXY, srcEnergy, tmpCircol;
for(k=0;k<circRow;k++){
Mat tmpSrc;
/************图像梯度计算********************/
cvtColor(tmp, tmpSrc, CV_BGR2GRAY);
srcXY = getTi(tmpSrc);
Mat tmpXY;
srcXY.convertTo(tmpXY, CV_8UC1);
imshow("srcXY", tmpXY);
/**************能量图和左边偏移图计算*********/
tmpCircol = Mat::zeros(tmp.rows, tmp.cols, CV_8UC1);
srcEnergy = getEnergy(srcXY, tmpCircol);
srcEnergy.convertTo(srcEnergy, CV_8UC1);
imshow("srcEnergy", srcEnergy);
/**************最小能量线计算*****************/
getCircolAddr(srcEnergy, tmpCircol, cirColAddr);
/**************显示最小能量线*****************/
Mat ttt;
tmp.copyTo(ttt);
for(i=0;i<tmp.rows;i++){
ttt.at<uchar>(i, cirColAddr[i]*3+0) = 0;
ttt.at<uchar>(i, cirColAddr[i]*3+1) = 0;
ttt.at<uchar>(i, cirColAddr[i]*3+2) = 255;
}
imshow("ttt", ttt);
/****************删除能量线像素并融合**********/
out = Mat::zeros(tmp.rows, tmp.cols-1, CV_8UC3);
for(i=0;i<tmp.rows;i++){
uchar *ptr1 = tmp.ptr(i);
uchar *ptr2 = out.ptr(i);
for(j=0;j<tmp.cols;j++){
if(j < cirColAddr[i]-1){
ptr2[j*3+0] = ptr1[j*3+0];
ptr2[j*3+1] = ptr1[j*3+1];
ptr2[j*3+2] = ptr1[j*3+2];
}else if(j == cirColAddr[i]-1){
ptr2[j*3+0] = (ptr1[j*3+0] + ptr1[(j+2)*3+0])/2;
ptr2[j*3+1] = (ptr1[j*3+1] + ptr1[(j+2)*3+1])/2;
ptr2[j*3+2] = (ptr1[j*3+2] + ptr1[(j+2)*3+2])/2;
}else if(j==cirColAddr[i]){
}
else if(j == cirColAddr[i]+1){
ptr2[(j-1)*3+0] = ptr2[(j-2)*3+0];
ptr2[(j-1)*3+1] = ptr2[(j-2)*3+1];
ptr2[(j-1)*3+2] = ptr2[(j-2)*3+2];
}else{
ptr2[(j-1)*3+0] = ptr1[j*3+0];
ptr2[(j-1)*3+1] = ptr1[j*3+1];
ptr2[(j-1)*3+2] = ptr1[j*3+2];
}
}
}
tmp = out;
waitKey(0);
}
return out;
}
int main(int argc, char *argv[]){
Mat src = imread(argv[1]);
imshow("src", src);
waitKey(10);
float scale = 2;
Mat out = getResultPic(src, scale);
imshow("out", out);
waitKey(0);
return 0;
}