图像拉伸 算法

uPlugin社区 2015-02-21 02:44:00
加精
大家好!
我想实现一个图片方块拉伸算法,类似于哈哈镜的功能,但是不知道如何入手。实现语言是C/C++,opencv图形库。效果如效果图。谢谢大家
...全文
4925 18 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
不可平庸 2016-03-15
  • 打赏
  • 举报
回复
这个用来做什么用? 做哈哈镜给小孩玩?
天外怪魔 2016-03-02
  • 打赏
  • 举报
回复
Mark一下,图形图像菜鸟路过。
微wx笑 2016-02-28
  • 打赏
  • 举报
回复
你这效果更像是被挤压形成的;
cj956686286 2016-02-24
  • 打赏
  • 举报
回复
都是大神 大学毕业设计搞的图像识别,很简单的亮条纹读取做了半年。
lm_whales 2016-02-21
  • 打赏
  • 举报
回复
先定义边缘到新的区域边缘的映射,然后在定义内部的映射方法
定义好映射后,求反向映射函数
blueink_200451 2016-02-20
  • 打赏
  • 举报
回复
shiter 2015-08-10
  • 打赏
  • 举报
回复
引用 10 楼 hahawaterbox 的回复:
楼主这种是不是叫做 image wraping ? 哥也实现了一种,不过与这个还是有点不同
上代码!
  • 打赏
  • 举报
回复
image warping的方法更满足需求吧
Cvsoftware 2015-06-18
  • 打赏
  • 举报
回复
楼主这种是不是叫做 image wraping ?


哥也实现了一种,不过与这个还是有点不同


NexTor 2015-02-27
  • 打赏
  • 举报
回复
如果要实现你那圆脸变方脸的变换的话,是否只需要找一个长方形到圆形的拉伸映射算法就可以了 感觉可以先将长方形变换到中心点基准,然后根据变换点的角度和距离比例到圆形中去找,是否可以完成这个圆脸到方脸的拉伸呀,不知道可不可行。
NexTor 2015-02-27
  • 打赏
  • 举报
回复
引用 2 楼 wangyaninglm 的回复:
主要还要添加一些线性插值的东西: http://blog.csdn.net/fengbingchun/article/details/17335477 你这个效果我还不太明白是怎么做到的,大家可以探讨一下
看代码的话,实现该效果的主要变换应该是void MaxFrame(IplImage* frame)函数中的
 
            int distance = (int)(tX * tX + tY * tY);
            if (distance < radius * radius)
            {
                newX = (int)((float)(tX) / 2.0);
                newY = (int)((float)(tY) / 2.0);
 
                newX = (int) (newX * (sqrt((double)distance) / real_radius));
                newX = (int) (newX * (sqrt((double)distance) / real_radius));
 
                newX = newX + center_X;
                newY = newY + center_Y;
 
                new_data[frame->widthStep * j + i * 3] = old_data[frame->widthStep * newY + newX * 3];
                new_data[frame->widthStep * j + i * 3 + 1] =old_data[frame->widthStep * newY + newX * 3 + 1];
                new_data[frame->widthStep * j + i * 3 + 2] =old_data[frame->widthStep * newY + newX * 3 + 2];
            }
      
代码中标红的代码是不是有问题,为什么newX做两次变换,还是说第二个应该是newY的变换呀。 这两行代码不用newX,newY来写会比较易懂些吧,将newX,real_radius,newY还原为tX,radius,tY newX = (int) ((int)((float)(tX) / 2.0) * (sqrt((double)distance) / (int)(radius / 2.0)); newY = (int) ((int)((float)(tY) / 2.0) * (sqrt((double)distance) / (int)(radius / 2.0)); 则除2省去, newX = (int) (tX* (sqrt((double)distance) / radius)); newY = (int) (tY * (sqrt((double)distance) / radius)); 那么tX,tY的像素值是原图中tX,tY对应点进行距离比例拉伸后对应点的像素值吧
uPlugin社区 2015-02-26
  • 打赏
  • 举报
回复
不对啊,这个效果应该是类似网格放缩
赵4老师 2015-02-26
  • 打赏
  • 举报
回复
使用3D Max将正常的照片贴图到边圆整过的四棱台上,再渲染。
shiter 2015-02-22
  • 打赏
  • 举报
回复
主要还要添加一些线性插值的东西: http://blog.csdn.net/fengbingchun/article/details/17335477 你这个效果我还不太明白是怎么做到的,大家可以探讨一下
shiter 2015-02-22
  • 打赏
  • 举报
回复

// haha_mirror.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"

#include<iostream>


#include "cv.h"
#include "highgui.h"
#include "math.h"
#include "opencv2/core/core.hpp"

#pragma comment(lib,"opencv_core2410d.lib")              
#pragma comment(lib,"opencv_highgui2410d.lib")              
#pragma comment(lib,"opencv_imgproc2410d.lib")   



#define DOWNRESIZE 0 // 缩小
#define UPRESIZE   1 // 放大
#define HORAO      2 // 水平外凹
#define HORTU      3 // 水平外凸
#define LADDER     4 // 梯形变形
#define TRIANGLE   5 // 三角形变形
#define SSHAPE     6 // S形变形
#define WAVESHAPE  7 // 波浪形变形
#define Concentrated 8 //集中形变形
#define Scattered   9 // 散开形变形

#define RANGE     100 // 水平外凹或外凸的幅度
#define PI        3.1415926

using namespace std;
using namespace cv;

void MaxFrame(IplImage* frame)
{
	uchar* old_data = (uchar*)frame->imageData;
	uchar* new_data = new uchar[frame->widthStep * frame->height];

	int center_X = frame->width / 2;
	int center_Y = frame->height / 2;
	int radius = 400;
	int newX = 0;
	int newY = 0;

	int real_radius = (int)(radius / 2.0);
	for (int i = 0; i < frame->width; i++)
	{
		for (int j = 0; j < frame->height; j++)
		{
			int tX = i - center_X;
			int tY = j - center_Y;

			int distance = (int)(tX * tX + tY * tY);
			if (distance < radius * radius)
			{
				newX = (int)((float)(tX) / 2.0);
				newY = (int)((float)(tY) / 2.0);

				newX = (int) (newX * (sqrt((double)distance) / real_radius));
				newX = (int) (newX * (sqrt((double)distance) / real_radius));

				newX = newX + center_X;
				newY = newY + center_Y;

				new_data[frame->widthStep * j + i * 3] = old_data[frame->widthStep * newY + newX * 3];
				new_data[frame->widthStep * j + i * 3 + 1] =old_data[frame->widthStep * newY + newX * 3 + 1];
				new_data[frame->widthStep * j + i * 3 + 2] =old_data[frame->widthStep * newY + newX * 3 + 2];
			}
			else
			{
				new_data[frame->widthStep * j + i * 3] =  old_data[frame->widthStep * j + i * 3];
				new_data[frame->widthStep * j + i * 3 + 1] =  old_data[frame->widthStep * j + i * 3 + 1];
				new_data[frame->widthStep * j + i * 3 + 2] =  old_data[frame->widthStep * j + i * 3 + 2];
			}
		}
	}
	memcpy(old_data, new_data, sizeof(uchar) * frame->widthStep * frame->height);
	delete[] new_data;
}


void MinFrame(IplImage* frame)
{
	uchar* old_data = (uchar*)frame->imageData;
	uchar* new_data = new uchar[frame->widthStep * frame->height];

	int center_X = frame->width / 2;
	int center_Y = frame->height / 2;

	int radius = 0;
	double theta = 0;
	int newX = 0;
	int newY = 0;

	for (int i = 0; i < frame->width; i++)
	{
		for (int j = 0; j < frame->height; j++)
		{
			int tX = i - center_X;
			int tY = j - center_Y;

			theta = atan2((double)tY, (double)tX);
			radius = (int)sqrt((double)(tX * tX) + (double) (tY * tY));
			int newR = (int)(sqrt((double)radius) * 12);
			newX = center_X + (int)(newR * cos(theta));
			newY = center_Y + (int)(newR * sin(theta));

			if (!(newX > 0 && newX < frame->width))
			{
				newX = 0;
			}
			if (!(newY > 0 && newY < frame->height))
			{
				newY = 0;
			}

			new_data[frame->widthStep * j + i * 3] = old_data[frame->widthStep * newY + newX * 3];
			new_data[frame->widthStep * j + i * 3 + 1] =old_data[frame->widthStep * newY + newX * 3 + 1];
			new_data[frame->widthStep * j + i * 3 + 2] =old_data[frame->widthStep * newY + newX * 3 + 2];
		}
	}
	memcpy(old_data, new_data, sizeof(uchar) * frame->widthStep * frame->height);
	delete[] new_data;
}

// 哈哈镜制作
int main( int argc, char** argv )
{
	IplImage* pImg; //声明IplImage指针
	IplImage* pImg1; //声明IplImage指针
	int i,j;
	int method = 0;
	CvSize size;
	double tmp;

	method = 8;
	//method = HORAO;

	//载入图像
	pImg = cvLoadImage( "lena.jpg", 1);
	cvNamedWindow( "Image", 1 );//创建窗口
	cvShowImage( "Image", pImg );//显示图像
	printf("imageSize: %d height: %d, width: %d, nChannels: %d\n", pImg->imageSize, pImg->height, pImg->width, pImg->nChannels);

	//MaxFrame(pImg);
	//MinFrame(pImg);

	switch(method)
	{
		// 图像缩小
	case DOWNRESIZE:
		size = cvGetSize(pImg);
		size.width = (size.width>>3)<<2; // 在OpenCV里边,widthStep必须是4的倍数,从而实现字节对齐,有利于提高运算速度。
		size.height =  size.height>>1;
		pImg1 = cvCreateImage( size, IPL_DEPTH_8U, 1);
		printf("imageSize: %d height: %d, width: %d, nChannels: %d\n", pImg1->imageSize, pImg1->height, pImg1->width, pImg1->nChannels);
		for(i=0;i<pImg1->height;i++)
			for(j=0;j<pImg1->width;j++)
			{
				pImg1->imageData[i*pImg1->width+j] = pImg->imageData[i*2*pImg->width+j*2];
			}
			break;
			// 图像放大
	case UPRESIZE:
		/* 添加代码 */
		break;
		// 水平外凹
	case HORAO:
		pImg1 = cvCreateImage( cvGetSize(pImg), IPL_DEPTH_8U, 1);
		printf("imageSize: %d height: %d, width: %d, nChannels: %d\n", pImg1->imageSize, pImg1->height, pImg1->width, pImg1->nChannels);
		for(i=0;i<pImg1->height;i++)
		{
			tmp = RANGE*sin(i*PI/pImg1->height);
			for(j=tmp;j<pImg1->width-tmp;j++)
			{
				pImg1->imageData[i*pImg1->width+j] = pImg->imageData[i*pImg->width+(int)((j-tmp)*(pImg->width)/(pImg->width-2*tmp))];
			}
		}
		break;
		// 水平外凸
	case HORTU:
		/* 添加代码 */
		break;
		// 梯形变形
	case LADDER:
		/* 添加代码 */
		break;
		// 三角形变形
	case TRIANGLE:
		/* 添加代码 */
		break;
		// S形变形
	case SSHAPE:
		/* 添加代码 */
		break;
		// 波浪形变形
	case WAVESHAPE:
		/* 添加代码 */
		break;
	case Concentrated:
		MaxFrame(pImg);
		break;
	case Scattered:
		MinFrame(pImg);
		break;
	default:
		printf("no method support\n");
		break;
	}

	// 显示结果
	cvNamedWindow( "Image1", 1 );//创建窗口
	cvShowImage( "Image1", pImg );//显示图像

	cvWaitKey(0); //等待按键

	//销毁窗口 释放内存
	cvDestroyWindow( "Image" );//销毁窗口
	cvReleaseImage( &pImg ); //释放图像
	cvDestroyWindow( "Image1" );//销毁窗口
	cvReleaseImage( &pImg1 ); //释放图像

	return 0;

}

网上找的代码,凑活能用
  • 打赏
  • 举报
回复
应该先进行人脸检测,然后进行人脸的缩放
wyx100 2015-02-22
  • 打赏
  • 举报
回复
引用 1 楼 wangyaninglm 的回复:

// haha_mirror.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"

#include<iostream>


#include "cv.h"
#include "highgui.h"
#include "math.h"
#include "opencv2/core/core.hpp"

#pragma comment(lib,"opencv_core2410d.lib")              
#pragma comment(lib,"opencv_highgui2410d.lib")              
#pragma comment(lib,"opencv_imgproc2410d.lib")   



#define DOWNRESIZE 0 // 缩小
#define UPRESIZE   1 // 放大
#define HORAO      2 // 水平外凹
#define HORTU      3 // 水平外凸
#define LADDER     4 // 梯形变形
#define TRIANGLE   5 // 三角形变形
#define SSHAPE     6 // S形变形
#define WAVESHAPE  7 // 波浪形变形
#define Concentrated 8 //集中形变形
#define Scattered   9 // 散开形变形

#define RANGE     100 // 水平外凹或外凸的幅度
#define PI        3.1415926

using namespace std;
using namespace cv;

void MaxFrame(IplImage* frame)
{
	uchar* old_data = (uchar*)frame->imageData;
	uchar* new_data = new uchar[frame->widthStep * frame->height];

	int center_X = frame->width / 2;
	int center_Y = frame->height / 2;
	int radius = 400;
	int newX = 0;
	int newY = 0;

	int real_radius = (int)(radius / 2.0);
	for (int i = 0; i < frame->width; i++)
	{
		for (int j = 0; j < frame->height; j++)
		{
			int tX = i - center_X;
			int tY = j - center_Y;

			int distance = (int)(tX * tX + tY * tY);
			if (distance < radius * radius)
			{
				newX = (int)((float)(tX) / 2.0);
				newY = (int)((float)(tY) / 2.0);

				newX = (int) (newX * (sqrt((double)distance) / real_radius));
				newX = (int) (newX * (sqrt((double)distance) / real_radius));

				newX = newX + center_X;
				newY = newY + center_Y;

				new_data[frame->widthStep * j + i * 3] = old_data[frame->widthStep * newY + newX * 3];
				new_data[frame->widthStep * j + i * 3 + 1] =old_data[frame->widthStep * newY + newX * 3 + 1];
				new_data[frame->widthStep * j + i * 3 + 2] =old_data[frame->widthStep * newY + newX * 3 + 2];
			}
			else
			{
				new_data[frame->widthStep * j + i * 3] =  old_data[frame->widthStep * j + i * 3];
				new_data[frame->widthStep * j + i * 3 + 1] =  old_data[frame->widthStep * j + i * 3 + 1];
				new_data[frame->widthStep * j + i * 3 + 2] =  old_data[frame->widthStep * j + i * 3 + 2];
			}
		}
	}
	memcpy(old_data, new_data, sizeof(uchar) * frame->widthStep * frame->height);
	delete[] new_data;
}


void MinFrame(IplImage* frame)
{
	uchar* old_data = (uchar*)frame->imageData;
	uchar* new_data = new uchar[frame->widthStep * frame->height];

	int center_X = frame->width / 2;
	int center_Y = frame->height / 2;

	int radius = 0;
	double theta = 0;
	int newX = 0;
	int newY = 0;

	for (int i = 0; i < frame->width; i++)
	{
		for (int j = 0; j < frame->height; j++)
		{
			int tX = i - center_X;
			int tY = j - center_Y;

			theta = atan2((double)tY, (double)tX);
			radius = (int)sqrt((double)(tX * tX) + (double) (tY * tY));
			int newR = (int)(sqrt((double)radius) * 12);
			newX = center_X + (int)(newR * cos(theta));
			newY = center_Y + (int)(newR * sin(theta));

			if (!(newX > 0 && newX < frame->width))
			{
				newX = 0;
			}
			if (!(newY > 0 && newY < frame->height))
			{
				newY = 0;
			}

			new_data[frame->widthStep * j + i * 3] = old_data[frame->widthStep * newY + newX * 3];
			new_data[frame->widthStep * j + i * 3 + 1] =old_data[frame->widthStep * newY + newX * 3 + 1];
			new_data[frame->widthStep * j + i * 3 + 2] =old_data[frame->widthStep * newY + newX * 3 + 2];
		}
	}
	memcpy(old_data, new_data, sizeof(uchar) * frame->widthStep * frame->height);
	delete[] new_data;
}

// 哈哈镜制作
int main( int argc, char** argv )
{
	IplImage* pImg; //声明IplImage指针
	IplImage* pImg1; //声明IplImage指针
	int i,j;
	int method = 0;
	CvSize size;
	double tmp;

	method = 8;
	//method = HORAO;

	//载入图像
	pImg = cvLoadImage( "lena.jpg", 1);
	cvNamedWindow( "Image", 1 );//创建窗口
	cvShowImage( "Image", pImg );//显示图像
	printf("imageSize: %d height: %d, width: %d, nChannels: %d\n", pImg->imageSize, pImg->height, pImg->width, pImg->nChannels);

	//MaxFrame(pImg);
	//MinFrame(pImg);

	switch(method)
	{
		// 图像缩小
	case DOWNRESIZE:
		size = cvGetSize(pImg);
		size.width = (size.width>>3)<<2; // 在OpenCV里边,widthStep必须是4的倍数,从而实现字节对齐,有利于提高运算速度。
		size.height =  size.height>>1;
		pImg1 = cvCreateImage( size, IPL_DEPTH_8U, 1);
		printf("imageSize: %d height: %d, width: %d, nChannels: %d\n", pImg1->imageSize, pImg1->height, pImg1->width, pImg1->nChannels);
		for(i=0;i<pImg1->height;i++)
			for(j=0;j<pImg1->width;j++)
			{
				pImg1->imageData[i*pImg1->width+j] = pImg->imageData[i*2*pImg->width+j*2];
			}
			break;
			// 图像放大
	case UPRESIZE:
		/* 添加代码 */
		break;
		// 水平外凹
	case HORAO:
		pImg1 = cvCreateImage( cvGetSize(pImg), IPL_DEPTH_8U, 1);
		printf("imageSize: %d height: %d, width: %d, nChannels: %d\n", pImg1->imageSize, pImg1->height, pImg1->width, pImg1->nChannels);
		for(i=0;i<pImg1->height;i++)
		{
			tmp = RANGE*sin(i*PI/pImg1->height);
			for(j=tmp;j<pImg1->width-tmp;j++)
			{
				pImg1->imageData[i*pImg1->width+j] = pImg->imageData[i*pImg->width+(int)((j-tmp)*(pImg->width)/(pImg->width-2*tmp))];
			}
		}
		break;
		// 水平外凸
	case HORTU:
		/* 添加代码 */
		break;
		// 梯形变形
	case LADDER:
		/* 添加代码 */
		break;
		// 三角形变形
	case TRIANGLE:
		/* 添加代码 */
		break;
		// S形变形
	case SSHAPE:
		/* 添加代码 */
		break;
		// 波浪形变形
	case WAVESHAPE:
		/* 添加代码 */
		break;
	case Concentrated:
		MaxFrame(pImg);
		break;
	case Scattered:
		MinFrame(pImg);
		break;
	default:
		printf("no method support\n");
		break;
	}

	// 显示结果
	cvNamedWindow( "Image1", 1 );//创建窗口
	cvShowImage( "Image1", pImg );//显示图像

	cvWaitKey(0); //等待按键

	//销毁窗口 释放内存
	cvDestroyWindow( "Image" );//销毁窗口
	cvReleaseImage( &pImg ); //释放图像
	cvDestroyWindow( "Image1" );//销毁窗口
	cvReleaseImage( &pImg1 ); //释放图像

	return 0;

}

网上找的代码,凑活能用
shiter 2015-02-22
  • 打赏
  • 举报
回复
我写了一下,看看还有啥好的,哈哈 http://blog.csdn.net/wangyaninglm/article/details/43902103

19,471

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 图形处理/算法
社区管理员
  • 图形处理/算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧