Nov 29th,去了一下楼上寝室膜拜了一下沙漠君,得到了它们目前的工作进展,是一份高级程序语言的作业 … 啊,当时我就惊了…
xiaodai : “我的这个还不是很好的,Xueyr 的作业在缩放的时侯用了多线程。。。”
xiaodao :”。#啊啊啊啊。。。要怎么在 Xcode 里实现多帧刷屏呢?。。”
//by SHA Mo
//Visual Studio 2010 + OpenCV 2.1
#include
#include
#include
#include
#include
#include
using namespace std;
//声明鼠标回调函数
void my_mouse_callback(int event, int x, int y, int flags, void* param);
//图的分辨率
const int IMAGE_SIZE_WID = 640;
const int IMAGE_SIZE_HGT = 480;
//自动缩放图像分割数
const int split_wid = 4;
const int split_hgt = 4;
//迭代次数上界
const int ITERATION_TIME = 200;
//过度动画帧数
const int TRANSITION_IMAGE = 20;
//过度动画帧速
const int TRANSITION_TIME = 1;
//茱莉亚集合参数
double j_re = -0.835;
double j_im = -0.2350;
//图的缩放比
double zoomRatio_WID = 4;
double zoomRatio_HGT = 3;
//函数图象的平移量
double mov_re = -2.5;
double mov_im = -1.5;
//上色控量
const double PI = acos(-1.0);
double ratio_r = 30;
double ratio_g = 25;
double ratio_b = 20;
double phase_r = 0;
double phase_g = 0;
double phase_b = 0.25;
//鼠标事件所需量
CvRect box;
bool drawing_box = false;
bool moving = false;
int mov_x;
int mov_y;
//鼠标实时位置
CvPoint mousePoint;
//判断一个复数是否属于Mandelbrot_Set
int mSetTest(double c_re, double c_im) {
int current_time = 1;
double z_re = 0;
double z_im = 0;
while ( z_re*z_re + z_im*z_im < 4 && current_time < ITERATION_TIME) {
++current_time;
double t_re = z_re*z_re - z_im*z_im + c_re;
z_im = 2*z_re*z_im + c_im;
z_re = t_re;
}
if (current_time == ITERATION_TIME) return 0;
else return current_time;
}
//判断一个复数是否属于Julia_Set
int jSetTest(double c_re, double c_im) {
int current_time = 1;
while ( c_re*c_re + c_im*c_im < 4 && current_time < ITERATION_TIME) {
++current_time;
double t_re = c_re*c_re - c_im*c_im + j_re;
c_im = 2*c_re*c_im + j_im;
c_re = t_re;
}
if (current_time == ITERATION_TIME) return 0;
else return current_time;
}
//计算像素点的颜色
CvScalar whatColor(int x, int y) {
//七彩颜色库:红橙黄绿蓝靛紫
CvScalar colorLib[7] = {{0, 0, 255},{15, 123, 255},{15, 255, 255},{15, 255, 33},{255, 141, 16},{255, 15, 69},{201, 15, 255}};
CvScalar black = {0, 0, 0};
CvScalar color;
int step = jSetTest(mov_re + x/(double)IMAGE_SIZE_WID*zoomRatio_WID, mov_im + y/(double)IMAGE_SIZE_HGT*zoomRatio_HGT);
if (step) {
//不属于分型集合
//color = colorLib[(step + 5) % 7];
color.val[0] = 127.5 - 127.5 * cos(step / ratio_b + phase_b * PI);
color.val[1] = 127.5 - 127.5 * cos(step / ratio_g + phase_g * PI);
color.val[2] = 127.5 - 127.5 * cos(step / ratio_r + phase_r * PI);
}
else {
//属于分型集合
color = black;
}
return color;
}
//绘制选定框
void draw_box( IplImage* img, CvRect rect ) {
cvRectangle (
img,
cvPoint(box.x, box.y),
cvPoint(box.x+box.width, box.y+box.height),
cvScalar(0x00, 0xff, 0x00)
);
}
//绘制图像
void draw( IplImage* image ) {
for (int i = 0; i < IMAGE_SIZE_WID; ++i)
for (int j = 0; j < IMAGE_SIZE_HGT; ++j) {
cvSet2D(image, j, i, whatColor(i, j));
}
}
//自定义可以越界的取色函数
CvScalar my_cvGet2D(IplImage* image, int x, int y)
{
//越界返回黑色
if (x<0 || y<0 || x>=IMAGE_SIZE_WID || y>=IMAGE_SIZE_HGT) return cvScalar(0x00, 0x00, 0x00);
return cvGet2D(image, y, x);
}
//拷贝图像矩形区域(允许越界,越界部分填黑,ROI实现)
IplImage* my_cvCloneImageRect(IplImage* src, CvRect rect) {
IplImage *dst = cvCreateImage(cvSize(rect.width, rect.height), src->depth, src->nChannels);
cvSetZero(dst);
//计算src的ROI矩形
CvRect src_rect;
src_rect.x = max(0, rect.x);
src_rect.y = max(0, rect.y);
src_rect.width = min(src->width, rect.x + rect.width) - src_rect.x;
src_rect.height = min(src->height, rect.y + rect.height) - src_rect.y;
if (src_rect.width <= 0 || src_rect.height <= 0) {
src_rect.width = 0;
src_rect.height = 0;
}
//计算dst的ROI矩形
CvRect dst_rect;
dst_rect.x = max(0, -rect.x);
dst_rect.y = max(0, -rect.y);
dst_rect.width = min(rect.width, -rect.x + src->width) - dst_rect.x;
dst_rect.height = min(rect.height, -rect.y + src->height) - dst_rect.y;
if (dst_rect.width <= 0 || dst_rect.height <= 0) {
dst_rect.width = 0;
dst_rect.height = 0;
}
if (src_rect.width!=0 && src_rect.height!=0 && dst_rect.width!=0 && dst_rect.height!=0) {
cvSetImageROI(src, src_rect);
cvSetImageROI(dst, dst_rect);
cvResize(src, dst);
cvResetImageROI(src);
cvResetImageROI(dst);
}
return dst;
}
//显示过度效果
IplImage* show_transition(IplImage* image, CvRect &box) {
IplImage* tmp = cvCloneImage( image );
for (int k = 1; k <= TRANSITION_IMAGE; ++k) {
//计算分步缩放的临时选定框
double tmp_x = box.x * (double)k/TRANSITION_IMAGE;
double tmp_y = box.y * (double)k/TRANSITION_IMAGE;
double tmp_width = IMAGE_SIZE_WID - (IMAGE_SIZE_WID - box.x - box.width) * (double)k/TRANSITION_IMAGE - tmp_x;
double tmp_height = IMAGE_SIZE_HGT - (IMAGE_SIZE_HGT - box.y - box.height) * (double)k/TRANSITION_IMAGE - tmp_y;
CvRect tmp_box = cvRect(tmp_x, tmp_y, tmp_width, tmp_height);
cvResize(my_cvCloneImageRect(image, tmp_box), tmp);
cvShowImage("HelloOpenCV", tmp);
cvWaitKey( TRANSITION_TIME );
}
return tmp;
}
//移动缩放图像(增加动态动画效果)
void move_zoom_image(IplImage* image, CvRect &box, bool transition = 1) {
IplImage* current_image = image;
//显示过度效果
if (transition) {
current_image = show_transition( image, box );
}
//改变函数图象的平移量
mov_re += (double)box.x/IMAGE_SIZE_WID*zoomRatio_WID;
mov_im += (double)box.y/IMAGE_SIZE_HGT*zoomRatio_HGT;
//改变图的缩放比
zoomRatio_WID *= (double)box.width/IMAGE_SIZE_WID;
zoomRatio_HGT *= (double)box.height/IMAGE_SIZE_HGT;
//刷新图像
draw( image );
}
//灰度图,开在函数内部会栈溢出
int grey_level[IMAGE_SIZE_WID][IMAGE_SIZE_HGT];
//评估图像复杂度(多算子加权:信息熵、反差[灰度矩阵求法]、边缘比率)
double image_rect_complexity( IplImage* image, CvRect rect ) {
//各灰度像素数
int grey_level_count[256] = {};
//灰度总量
int grey_level_num = rect.width * rect.height;
//灰度共生矩阵
int GLCM[256][256] = {};
//抽取图像灰度信息
for (int i = rect.x; i < rect.x + rect.width; ++i)
for (int j = rect.y; j < rect.y + rect.height; ++j) {
grey_level[i][j] = ((uchar*)(image->imageData + j*image->widthStep))[i*image->nChannels + 0];
grey_level[i][j] += ((uchar*)(image->imageData + j*image->widthStep))[i*image->nChannels + 1];
grey_level[i][j] += ((uchar*)(image->imageData + j*image->widthStep))[i*image->nChannels + 2];
grey_level[i][j] /= 3;
++grey_level_count[ grey_level[i][j] ];
}
//计算灰度共生矩阵(△x=1,△y=1)和 边缘像素数
int edge_pixel = 0;
for (int i = rect.x; i < rect.x + rect.width - 1; ++i)
for (int j = rect.y; j < rect.y + rect.height - 1; ++j) {
++GLCM[grey_level[i][j]][grey_level[i+1][j+1]];
if (grey_level[i][j] != grey_level[i+1][j+1]) ++edge_pixel;
}
//计算信息熵
double inf_entropy = 0;
for (int i = 0; i < 256; ++i) if (grey_level_count[i] != 0) {
inf_entropy -= (double)grey_level_count[i]/grey_level_num * log((double)grey_level_count[i]/grey_level_num);
}
//计算反差
double contrast = 0;
for (int i = 0; i < 256; ++i)
for (int j = 0; j < 256; ++j) if (GLCM[i][j] != 0)
contrast = (double)GLCM[i][j]/grey_level_num * (i - j) * (i - j);
//边缘比率
double edge_ratio = edge_pixel / grey_level_num;
//返回加权图像复杂度
return contrast/2 + inf_entropy + edge_ratio;
}
//自动缩放
void auto_zoom( IplImage* image ) {
double max_complexity = 0;
CvRect max_complex_rect;
for (int i = 0; i < split_wid; ++i)
for (int j = 0; j < split_hgt; ++j) {
double tmp_complexity = image_rect_complexity( image,
cvRect( i*(IMAGE_SIZE_WID/split_wid),
j*(IMAGE_SIZE_HGT/split_hgt),
IMAGE_SIZE_WID/split_wid,
IMAGE_SIZE_HGT/split_hgt ) );
if (tmp_complexity > max_complexity) {
max_complex_rect = cvRect(
i*(IMAGE_SIZE_WID/split_wid),
j*(IMAGE_SIZE_HGT/split_hgt),
IMAGE_SIZE_WID/split_wid,
IMAGE_SIZE_HGT/split_hgt );
max_complexity = tmp_complexity;
}
}
move_zoom_image( image, max_complex_rect );
}
int main( int argc, char* argv[] ) {
//初始化选定框变量
box = cvRect(-1, -1, 0, 0);
//创建图像
IplImage* pImg = cvCreateImage (/*size*/cvSize (IMAGE_SIZE_WID, IMAGE_SIZE_HGT), /*depth*/IPL_DEPTH_8U, /*nChannels*/3);
cvSetZero(pImg);
IplImage* temp = cvCloneImage( pImg );
//创建窗口
cvNamedWindow (/*name of the window*/"HelloOpenCV", 1);
//标志鼠标事件
cvSetMouseCallback("HelloOpenCV", my_mouse_callback, (void*) pImg);
//初始化图像
draw( pImg );
//反复获取用户交互信息并处理
while ( 1 ) {
CvFont font;
double hScale = 1.0;
double vScale = 1.0;
int lineWidth = 1;
cvCopyImage( pImg, temp );
//实时绘制选定框
if ( drawing_box ) draw_box( temp, box );
//按住右键时拖动画面
if ( moving ) {
CvRect tmp_box = cvRect(mov_x - mousePoint.x , mov_y - mousePoint.y, pImg->width, pImg->height);
cvResize(my_cvCloneImageRect(pImg, tmp_box), temp);
}
//实时显示鼠标位置对应的复数坐标系的坐标
cvInitFont(&font, CV_FONT_HERSHEY_DUPLEX, hScale, vScale, 0, lineWidth);
char x_coord[10];
itoa((int)mousePoint.x, x_coord, 10);
char y_coord[10];
itoa((int)mousePoint.y, y_coord, 10);
cvPutText(temp, strcat(strcat(x_coord, ","), y_coord), mousePoint, &font, cvScalar(0x00, 0x00, 0xff));
cvShowImage( "HelloOpenCV", temp);
//输入ESC后退出
int key_num = cvWaitKey( 20 );
if ( key_num == 27 ) break;
else if ( key_num == 'r') {
CvRect normal = cvRect(0, 0, pImg->width, (int)(pImg->height / ((zoomRatio_HGT/zoomRatio_WID)/((double)IMAGE_SIZE_HGT/IMAGE_SIZE_WID))));
move_zoom_image( pImg, normal );
//zoomRatio_HGT = zoomRatio_WID * IMAGE_SIZE_HGT / IMAGE_SIZE_WID;
//draw( pImg );
}
else if ( key_num == 'c') auto_zoom( pImg );
}
//关闭窗口、释放图像
cvReleaseImage( &pImg );
cvReleaseImage( &temp );
cvDestroyWindow( "HelloOpenCV" );
return 0;
}
//定义鼠标事件回调函数
void my_mouse_callback(int event, int x, int y, int flags, void* param) {
IplImage* image = (IplImage*) param;
switch ( event ) {
//鼠标拖动
case CV_EVENT_MOUSEMOVE :
mousePoint = cvPoint(x, y);
//左键拖动时实时维护选定框
if (flags & CV_EVENT_FLAG_LBUTTON) {
drawing_box = true;
if ( drawing_box ) {
box.width = x - box.x;
box.height = y - box.y;
}
}
else if (flags & CV_EVENT_FLAG_RBUTTON) {
moving = true;
}
break;
//左键按下
case CV_EVENT_LBUTTONDOWN:
drawing_box = false;
box = cvRect(x,y,0,0);
break;
//左键抬起
case CV_EVENT_LBUTTONUP:
if (drawing_box) {
drawing_box = false;
//确保选定框长宽正值
if (box.width < 0) {
box.x += box.width;
box.width *= -1;
}
if (box.height < 0) {
box.y += box.height;
box.height *= -1;
}
move_zoom_image(image, box);
}
else {
box = cvRect(x-IMAGE_SIZE_WID/2, y-IMAGE_SIZE_HGT/2, IMAGE_SIZE_WID, IMAGE_SIZE_HGT);
move_zoom_image(image, box);
}
break;
//右键按下
case CV_EVENT_RBUTTONDOWN:
moving = false;
mov_x = x;
mov_y = y;
break;
//右键放开
case CV_EVENT_RBUTTONUP:
if (moving) {
moving = false;
box = cvRect(mov_x - x, mov_y - y, IMAGE_SIZE_WID, IMAGE_SIZE_HGT);
move_zoom_image(image, box, 0);
}
else {
box = cvRect(-IMAGE_SIZE_WID/2, -IMAGE_SIZE_HGT/2, IMAGE_SIZE_WID*2, IMAGE_SIZE_HGT*2);
move_zoom_image(image, box);
}
break;
}
}
/*
1100300627 薛怡然 制作
环境 Visual Studio 2010 + OpenCV 2.1
Code::Blocks 10.05 + MinGW 4.4.1 + OpenCV 2.1
本机编译、运行通过
实现功能:Task 2 ~ Task 6
附加功能:右键拖动平移、多重采样抗锯齿、动画缩放、朱利亚集、多线程绘图、多线程搜索复杂区域、用户配置文件等
*/
#include //C++
#include
#include
#include //STL
#include
#include
#include //C
#include
#include
#include //WIN32
#include //OpenCV
#include
#define LIMIT_SQUARE 4 //迭代阈值(2)的平方
//以下全局变量可通过设置函数读取 config.ini 进行更改
char name_m[] = "Mandelbrot"; //窗口名
char name_j[] = "Julia";
char* window_name = name_m;
double julia_set = false; //分形种类:false:曼得波罗集 true:朱利亚集
//为统一接口,定义:
//曼得波罗集: z[n+1] = z[n]^2 + c
//朱利亚集: c[n+1] = c[n]^2 + j_c
double j_c_re = -0.726895347709114071439; //朱利亚集中 j_c 的实部
double j_c_im = 0.188887129043845954792; //朱利亚集中 j_c 的虚部
bool ssaa = true; //4x多重采样抗锯齿开关
int max_iteration = 300; //最大迭代次数
int img_width = 800; //图像宽度
int img_height = 600; //图像高度
int animation = 20; //动画缩放效果步数
int max_zoom = 10; //自动缩放最大次数
int zoom_partition = 4; //自动缩放画面每轴分区数
int zoom_delay = 3000; //自动缩放延迟(毫秒)
double ctr_re = -0.5, ctr_im = 0; //图像中心复平面坐标
double img_left = -2; //图像左边缘复平面实轴坐标
int draw_partition = 8; //绘图线程数(一般会再多出一个)
int draw_thread = 0; //绘图线程返回计数
int beauty_thread = 0; //区域复杂度线程返回计数
IplImage *img, *tmp; //img:主体图像 tmp:用于动态显示的临时图像
CvRect box; //临时线框
bool drawing_box = false; //绘制线框状态
CvPoint move_from, move_to; //右键平移范围
bool moving = false; //右键平移状态
double pi = acos(-1.0); //上色三角函数用 π
double ratio_r = 30; //上色三角函数自变量系数(倒数)
double ratio_g = 25;
double ratio_b = 20;
double phase_r = 0; //上色三角函数初相 / π
double phase_g = 0;
double phase_b = 0.25;
using namespace std;
using namespace cv;
//测试C是否属于M_Set
int xMSetTest(double c_re, double c_im) {
double z_re = 0, z_im = 0, temp;
int step = 0;
while (z_re*z_re + z_im*z_im < LIMIT_SQUARE && step != max_iteration) {
temp = z_re * z_re - z_im * z_im;
z_im = 2 * z_re * z_im + c_im;
z_re = temp + c_re;
step++;
}
if (z_re*z_re + z_im*z_im < LIMIT_SQUARE && step == max_iteration)
return 0;
else return step;
}
//测试C是否属于J_SET
int xJSetTest(double c_re, double c_im) {
double temp;
int step = 0;
while (c_re*c_re + c_im*c_im < LIMIT_SQUARE && step != max_iteration) {
temp = c_re * c_re - c_im * c_im;
c_im = 2 * c_re * c_im + j_c_im;
c_re = temp + j_c_re;
step++;
}
if (c_re*c_re + c_im*c_im < LIMIT_SQUARE && step == max_iteration)
return 0;
else return step;
}
//测试函数指针,用于给 M_SET 与 J_SET 测试提供同样接口
int (*xSetTest)(double c_re, double c_im) = xMSetTest;
//整型绝对值
inline int xAbs(int x) {
return (x > 0) ? x : -x;
}
//像素坐标转换至复平面坐标(实轴)
inline double xRe(double x) {
return ctr_re + (2 * x - img_width)
* (ctr_re - img_left) / img_width;
}
//像素坐标转换至复平面坐标(虚轴)
inline double xIm(double y) {
return ctr_im - (2 * y - img_height)
* (ctr_re - img_left) / img_width;
}
//拷贝图像矩形区域(允许越界,越界部分填黑)
IplImage* xCloneImageOver(IplImage* src, CvRect rect) {
IplImage *dst = cvCreateImage(cvSize(rect.width, rect.height), src->depth, src->nChannels);
cvSetZero(dst);
CvRect src_range = rect;
CvRect dst_range = cvRect(0, 0, rect.width, rect.height);
//检查四侧越界,适当缩小复制范围
if (src_range.x < 0) {
src_range.width += src_range.x;
dst_range.width += src_range.x;
dst_range.x -= src_range.x;
src_range.x = 0;
}
if (src_range.y < 0) {
src_range.height += src_range.y;
dst_range.height += src_range.y;
dst_range.y -= src_range.y;
src_range.y = 0;
}
if (src_range.x + src_range.width > src->width) {
int diff = src_range.x + src_range.width - src->width;
src_range.width -= diff;
dst_range.width -= diff;
}
if (src_range.y + src_range.height > src->height) {
int diff = src_range.y + src_range.height - src->height;
src_range.height -= diff;
dst_range.height -= diff;
}
//检查完全越界状态
if (src_range.height <= 0 || src_range.width <= 0) return dst;
//复制图像内容
for (int i = 0; i < src_range.height; i++) {
char* src_ptr = src->imageData + (src_range.y + i) * src->widthStep +
src_range.x * (src->depth / 8) * src->nChannels;
char* dst_ptr = dst->imageData + (dst_range.y + i) * dst->widthStep +
dst_range.x * (src->depth / 8) * src->nChannels;
memcpy(dst_ptr, src_ptr, src_range.width * (src->depth / 8) * src->nChannels);
}
return dst;
}
//定义像素颜色 & 4xAA
CvScalar xColorAA(double x, double y) {
double result[4];
CvScalar color = cvScalar(0);
result[0] = xSetTest(xRe(x - 0.125), xIm(y - 0.25));
result[1] = xSetTest(xRe(x + 0.25), xIm(y - 0.125));
result[2] = xSetTest(xRe(x + 0.125), xIm(y + 0.25));
result[3] = xSetTest(xRe(x - 0.25), xIm(y + 0.125));
for (int i=0; i<4; i++) {
if (result[i]) {
color.val[0] += 127.5 - 127.5 * cos(result[i] / ratio_b + phase_b * pi);
color.val[1] += 127.5 - 127.5 * cos(result[i] / ratio_g + phase_g * pi);
color.val[2] += 127.5 - 127.5 * cos(result[i] / ratio_r + phase_r * pi);
} else {
color.val[0] += 0;
color.val[1] += 0;
color.val[2] += 0;
}
}
color.val[0] /= 4;
color.val[1] /= 4;
color.val[2] /= 4;
return color;
}
//定义像素颜色 & noAA
CvScalar xColorNoAA(double x, double y) {
double result = xSetTest(xRe(x),xIm(y));
CvScalar color;
if (result) {
color.val[0] = 127.5 - 127.5 * cos(result / ratio_b + phase_b * pi);
color.val[1] = 127.5 - 127.5 * cos(result / ratio_g + phase_g * pi);
color.val[2] = 127.5 - 127.5 * cos(result / ratio_r + phase_r * pi);
} else {
color.val[0] = 0;
color.val[1] = 0;
color.val[2] = 0;
}
return color;
}
//定义像素颜色函数指针,用于给 xColorAA 和 xColorNoAA 提供同样接口
CvScalar (*xColor)(double x, double y) = xColorNoAA;
//单个绘制图像线程
DWORD WINAPI xDrawThread(LPVOID param) {
pair *range = (pair*)param;
for (int i=range->first; isecond; i++) {
for (int j=0; j > param(draw_partition + 1);
draw_thread = 0;
//多线程绘制
for (int i=0; i 10000) x = 0;
if (y > 10000) y = 0;
if (flags & CV_EVENT_FLAG_LBUTTON) { //左键拖动
drawing_box = true;
box.width = x - box.x;
box.height = y - box.y;
if (xAbs(box.width) * img_height > xAbs(box.height) * img_width) {
box.height = ((box.height > 0) ? 1 : -1) *
xAbs(box.width) * img_height / img_width;
} else {
box.width = ((box.width > 0) ? 1 : -1) *
xAbs(box.height) * img_width / img_height;
}
} else if (flags & CV_EVENT_FLAG_RBUTTON) { //右键拖动
moving = true;
move_to.x = 2 * move_from.x - x;
move_to.y = 2 * move_from.y - y;
}
break;
case CV_EVENT_LBUTTONDOWN: //左键按下
drawing_box = false;
box = cvRect(x,y,0,0);
break;
case CV_EVENT_LBUTTONUP: //左键放开
if (drawing_box && xAbs(box.width) > 2) {
drawing_box = false;
if (box.width < 0) {
box.x += box.width;
box.width *= -1;
}
if (box.height < 0) {
box.y += box.height;
box.height *= -1;
}
xZoom(box);
} else {
drawing_box = false;
xZoom(cvRect(x - img_width / 2, y - img_height / 2,
img_width, img_height));
}
break;
case CV_EVENT_RBUTTONDOWN: //右键按下
moving = false;
move_from.x = x;
move_from.y = y;
break;
case CV_EVENT_RBUTTONUP: //右键放开
if (moving) {
moving = false;
double t_ctr_re = xRe(move_to.x - move_from.x + img_width / 2.0);
double t_ctr_im = xIm(move_to.y - move_from.y + img_height / 2.0);
img_left = xRe(move_to.x - move_from.x);
ctr_re = t_ctr_re;
ctr_im = t_ctr_im;
xReDraw();
} else {
xZoom(cvRect(x, y, 0, 0), 0.5);
}
break;
}
}
//计算区域复杂度线程参数
struct BeautyParam {
double result;
CvPoint begin, end;
};
//计算区域复杂度线程
DWORD WINAPI xBeautyThread(LPVOID thread_param) {
BeautyParam *param = (BeautyParam*)thread_param;
int real_num = (param->end.x - param->begin.x) * (param->end.y - param->begin.y);
int color_num = real_num;
CvScalar average = cvScalar(0);
param->result = 0;
uchar *ptr;
//计算平均值,黑色不计
for (int i=param->begin.y; iend.y; i++) {
ptr = (uchar*)(img->imageData + i * img->widthStep);
for (int j=param->begin.x; jend.x; j++) {
if (ptr[3 * j] || ptr[3 * j + 1] || ptr[3 * j + 2]) {
average.val[0] += ptr[3 * j];
average.val[1] += ptr[3 * j + 1];
average.val[2] += ptr[3 * j + 2];
} else {
color_num--;
}
}
}
if (color_num) {
average.val[0] /= color_num;
average.val[1] /= color_num;
average.val[2] /= color_num;
}
//计算方差,黑色不计入平方和,但计入分母数
for (int i=param->begin.y; iend.y; i++) {
ptr = (uchar*)(img->imageData + i * img->widthStep);
for (int j=param->begin.x; jend.x; j++) {
if (ptr[3 * j] || ptr[3 * j + 1] || ptr[3 * j + 2]) {
param->result += (ptr[3 * j] - average.val[0]) *
(ptr[3 * j] - average.val[0]);
param->result += (ptr[3 * j + 1] - average.val[1]) *
(ptr[3 * j + 1] - average.val[1]);
param->result += (ptr[3 * j + 2] - average.val[2]) *
(ptr[3 * j + 2] - average.val[2]);
}
}
}
param->result /= real_num;
beauty_thread--;
return 0;
}
//查找复杂区域
int xFindBeauty(){
vector param(zoom_partition * zoom_partition);
int unit_x = img_width / zoom_partition;
int unit_y = img_height / zoom_partition;
CvRNG seed = cvRNG(time(0));
//图像分区,多线程计算方差
beauty_thread = 0;
for (int i=0; i param[max].result) max = i;
}
return max;
};
//自动查找复杂区域并缩放
void xAutoZoom() {
int zoom_to;
int unit_x = img_width / zoom_partition;
int unit_y = img_height / zoom_partition;
CvRect auto_box;
cout << "Auto Zoom" << endl;
for (int i=0; i= 40 && img_height >= 40){
cvCopyImage(img, tmp);
cvRectangle(tmp, cvPoint(20, 20),
cvPoint(img_width - 20, img_height - 20),
cvScalar(0xff,0xff,0xff), 2);
cvRectangle(tmp, cvPoint(20, 20),
cvPoint(img_width - 20, img_height - 20),
cvScalar(0xff,0x00,0x00));
cvShowImage(window_name, tmp);
cvWaitKey(1000);
cvShowImage(window_name, img);
}
cout << "Manual Operate" << endl;
}
//循环绘制图像并接收用户输入
void xLoop() {
box = cvRect(-1,-1,0,0);
int key = 0;
xReDraw();
for (;;) {
if (drawing_box) { //左键选定矩形区域时
cvCopyImage(img,tmp);
cvRectangle(tmp,
cvPoint(box.x, box.y),
cvPoint(box.x + box.width, box.y + box.height),
cvScalar(0xff,0xff,0xff), 2);
cvRectangle(tmp,
cvPoint(box.x, box.y),
cvPoint(box.x + box.width, box.y + box.height),
cvScalar(0xff,0x00,0x00));
cvShowImage(window_name,tmp);
} else if (moving) { //右键拖动平移图像时
IplImage *move = xCloneImageOver(img, cvRect(
move_to.x - move_from.x,
move_to.y - move_from.y,
img_width,
img_height));
cvShowImage(window_name, move);
cvReleaseImage(&move);
} else { //空闲时
cvShowImage(window_name, img);
}
cvSetMouseCallback(window_name, xOnMouse);
if (drawing_box || moving) key = cvWaitKey(15);
else key = cvWaitKey(100);
if (key == 27) return;
if (key == 'a') xAutoZoom();
}
}
//读取设置文件
void xSetting() {
ifstream fi("config.ini");
string cmd;
double val;
//随机生成图像颜色
CvRNG seed = cvRNG(time(0));
ratio_r = cvRandReal(&seed) * 50 + 10;
ratio_g = cvRandReal(&seed) * 50 + 10;
ratio_b = cvRandReal(&seed) * 50 + 10;
phase_r = cvRandReal(&seed) * 2 * pi;
phase_g = cvRandReal(&seed) * 2 * pi;
phase_b = cvRandReal(&seed) * 2 * pi;
//读取用户设置
while (fi >> cmd >> val) {
if (cmd == "julia_set" && val == 1) {
julia_set = true;
window_name = name_j;
xSetTest = xJSetTest;
ctr_re = 0;
ctr_im = 0;
img_left = -1.5;
}
else if (cmd == "ssaa" || cmd == "4xAA") ssaa = (val != 0);
else if (cmd == "max_iteration") max_iteration = (int)val;
else if (cmd == "img_width" && val > 0) img_width = (int)val;
else if (cmd == "img_height" && val > 0) img_height = (int)val;
else if (cmd == "animation" && val >= 1) animation = (int)val;
else if (cmd == "max_zoom" && val >= 1) max_zoom = (int)val;
else if (cmd == "zoom_partition" && val >= 1) zoom_partition = (int)val;
else if (cmd == "zoom_delay" && val >= 1) zoom_delay = (int)val;
else if (cmd == "draw_partition" && val >= 1) draw_partition = (int)val;
else if (cmd == "ctr_re") ctr_re = val;
else if (cmd == "ctr_im") ctr_im = val;
else if (cmd == "img_left") img_left = val;
else if (cmd == "ratio_r" && val != 0) ratio_r = val;
else if (cmd == "ratio_g" && val != 0) ratio_g = val;
else if (cmd == "ratio_b" && val != 0) ratio_b = val;
else if (cmd == "phase_r") phase_r = val;
else if (cmd == "phase_r") phase_r = val;
else if (cmd == "phase_r") phase_r = val;
else if (cmd == "j_c_re") j_c_re = val;
else if (cmd == "j_c_im") j_c_im = val;
}
//检查复平面设置
if (img_left > ctr_re) img_left = 2 * ctr_re - img_left;
//设置计算像素颜色函数指针
if (ssaa) xColor = xColorAA;
}
//创建和删除图像
int main() {
xSetting();
cout << "Use mouse to zoom in, zoom out, or move the image." << endl;
cout << "Press A in the image window to enter Auto Zoom mode." << endl << endl;
img = cvCreateImage(cvSize(img_width, img_height),/*depth*/8,/*nChannels*/3);
tmp = cvCloneImage(img);
xLoop();
cvReleaseImage(&img);
cvReleaseImage(&tmp);
return 0;
}