Перейти к содержимому
Compvision.ru
olkin

motion blur

Recommended Posts

Ыаыаы у меня старая версия, не читает Ваши заголовочные) обновляю

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

У меня 2.4, не все заголовочные нужны,это у меня просто файл для экспериментов, там всего накидал.

Последовательное применение двух сверток по отрезку.



#include <iostream>
#include <vector>
#include <stdio.h>
#include <functional>
#include <algorithm>
#include <numeric>
#include <cstddef>
#include "opencv2/core/core.hpp"
#include "opencv2/core/gpumat.hpp"
#include "opencv2/core/opengl_interop.hpp"
#include "opencv2/gpu/gpu.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/contrib/contrib.hpp"
#include "opencv2/video/tracking.hpp"
#include "opencv2/imgproc/imgproc.hpp"
using namespace std;
using namespace cv;
// ---------------------------------
// src - исходное изображение
// p - точка, с которой начинается свертка
// v - направление вектора-ядра (орт вектора размытия)
// N - длина вектора размытия (ядра свертки)
// ---------------------------------
Vec3f ConvolvePoint(Mat& src,Point2f p,Vec2f v,int N)
{
Vec3f sum=0;
float k=1.0/(float)N;
for(int i=0;i<N;i++)
{
if(p.y+(float)i*v[1]>0 && p.y+(float)i*v[1]<src.rows && p.x+(float)i*v[0]>0 && p.x+(float)i*v[0]<src.cols)
{
sum+=k*src.at<Vec3f>(p.y+(float)i*v[1],p.x+(float)i*v[0]);
}
}
return sum;
}
// ---------------------------------
// Применяем размытие к изображению
// ---------------------------------
void Blur(Mat& src,Mat& dst)
{
// Углы для двух стадий размытия
float alpha1=45*CV_PI/180.0;
float alpha2=-30*CV_PI/180.0;

for(int i=0;i<src.rows;i++)
{
for(int j=0;j<src.cols;j++)
{
// Индексация матриц строка, столбец
// компоненты точки столбец, строка
// компоненты вектора столбец, строка

// последовательно, начиная от исходной точки производим свертку
// следующая свертка начинается там, где кончилась предыдущая.
// так как сумма коэффициентов каждой свертки равна 1, то результат последовательного
// применения ядер нужно разделить на количество этих ядер.

dst.at<Vec3f>(i,j)=(ConvolvePoint(src,Point2f(j,i),Vec2f(cos(alpha1),sin(alpha1)),10)+
ConvolvePoint(src,Point2f(j+10*sin(alpha1),i+10*cos(alpha1)),Vec2f(cos(alpha2),sin(alpha2)),10))/2;
}

}
}
// ---------------------------------
//
// ---------------------------------
int main( int argc, char** argv )
{
namedWindow("Image");
namedWindow("Labels");

Mat Img=imread("C:\\ImagesForTest\\skull.jpg",1);
Img.convertTo(Img,CV_32FC1,1.0/255.0);
int width=Img.cols;
int height=Img.rows;
Mat resim(Img.size(),CV_32FC3);
Blur(Img,resim);
imshow("Labels",resim);
imshow("Image",Img);
cvWaitKey(0);

}[/code]

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Делюсь впечатлениями)

Во первых, лучше никому не знать, какого года, оказывается, у меня была установлена версия OpenCV)) и насколько в 2.4.2 всё сразу легче пошло. Во вторых, огромное спасибо за код. Собственно, вот этот фрагмент

if(p.y+(float)i*v[1]>0 && p.y+(float)i*v[1]<src.rows && p.x+(float)i*v[0]>0 && p.x+(float)i*v[0]<src.cols)

                {

                        sum+=k*src.at<Vec3f>(p.y+(float)i*v[1],p.x+(float)i*v[0]);

и есть то изящное решение, на котором я стопорилась, у меня реализация выглядела несколько иначе, и в этом был основной косяк. Ну и, конечно, в той версии, немножко;) В общем, за это огромнейшее спасибо, вопрос шоколадки остался в силе. Сейчас дорабатываю всякие мелочи, в частности, там по краям рамка шириной в вектор не размывается, на Вашех скрине не видно, так как фон черный.

...А строит картинку оно у меня секунд 40, кстати. Но дело еще может быть в слабом рабочем ноуте.

На очереди сплайны, сгладить ломанную и пустить свертку уже по кривой:)

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Там надпись снизу, она размыта, может конечно с другой стороны не размывает, по картинке не видно.

Вообще, вроде бы должно размываться (цикл по всем точкам изображения идет), сейчас проверять лень.

Просто надо аккуратно проверить, что он на краях делает (может там ядро меньше, так и коэффициенты надо корректировать), ну в общем не люблю краевые эффекты,они обычно сильно программу усложняют. Хотя есть решение, которое ленивые челы, как я любят :) - это copyMakeBorder, советую посмотреть. Если кратко, то она делает поля заданной ширины вокруг изображения. Если поле сделать размером с краевой эффект, то все как бы само собой решается.

ЗЫ: Сложность алгоритма N*M*L, где N и M, ширина и высота изображения, а L количество точек в кривой свертки.

Вот и считайте.

ЗЫЗЫ: Идеальный алгоритм для распараллеливания на GPU. Раз 100 точно быстрее будет. См. CUDA.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Тестила на белой картинке с черный контуром квадрата в центре - оно наглядней всего. Верхний и правый края стали черно-белым градиентом четко по ширине вектора. Ну может и мой косяк, код-то не дословно слизан:)

copyMakeBorder - читала где-то, спасибо за подсказку, я тоже ленивый чел;)

Хех, мне до распаралеливания еще..)

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Вроде все неплохо.

post-1-0-20110400-1344460473_thumb.jpg

В смысле так и должно быть, ведь с краю, то ничего нет, вот он и намазывает нули.

Там просто коэффициент надо корректировать, ядро уменьшается, а делит как для полного, длиной L.

Вот что я имел ввиду:

post-1-0-33383700-1344460886_thumb.jpg

#include <iostream>
#include <vector>
#include <stdio.h>
#include <functional>
#include <algorithm>
#include <numeric>
#include <cstddef>
#include "opencv2/core/core.hpp"
#include "opencv2/core/gpumat.hpp"
#include "opencv2/core/opengl_interop.hpp"
#include "opencv2/gpu/gpu.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/contrib/contrib.hpp"
#include "opencv2/video/tracking.hpp"
#include "opencv2/imgproc/imgproc.hpp"
using namespace std;
using namespace cv;

Vec3f ConvolvePoint(Mat& src,Point2f p,Vec2f v)
{
Vec3f sum=0;
//float k=1.0/30.0; // По 10 точкам вектора
double L=0;
for(int i=0;i<30;i++)
{
if(p.y+(float)i*v[1]>0 && p.y+(float)i*v[1]<src.rows && p.x+(float)i*v[0]>0 && p.x+(float)i*v[0]<src.cols)
{
sum+=src.at<Vec3f>(p.y+(float)i*v[1],p.x+(float)i*v[0]);
L++;
}
}
if(L>0)
{
sum/=L;
}
return sum;
}
// ---------------------------------
//
// ---------------------------------
void Blur(Mat& src,Mat& dst)
{
for(int i=0;i<src.rows;i++)
{
for(int j=0;j<src.cols;j++)
{
dst.at<Vec3f>(i,j)=ConvolvePoint(src,Point2f(j,i),Vec2f(1,1)); // Vec2f(1,1) - вектор под 45 градусов
}

}
}
// ---------------------------------
//
// ---------------------------------
int main( int argc, char** argv )
{
namedWindow("Image");
namedWindow("Labels");

Mat Img=imread("C:\\ImagesForTest\\grid.png",1);
Img.convertTo(Img,CV_32FC1,1.0/255.0);
int width=Img.cols;
int height=Img.rows;
Mat resim(Img.size(),CV_32FC3);
Blur(Img,resim);
imshow("Labels",resim);
imshow("Image",Img);
cvWaitKey(0);

}[/code]

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Размывает не хуже чем в фотошопе, я сравнивала:) Рамка только. Походу, потому что

if(p.y+(float)i*v[1]>0 && p.y+(float)i*v[1]<src.rows && p.x+(float)i*v[0]>0 && p.x+(float)i*v[0]<src.cols)

вектор упирается в край, и там тормозит. Только, чего оно черным стало - фиг знает

ну да да. но леньки ж)

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

См. вверх ^ :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

По поводу этого топика: http://www.compvision.ru/forum/index.php?showtopic=935 чей это код (первоисточник)? его можно использовать в программе, ко мне не прийдут специально обученные дяди с вопросом про лицензию?)

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Там есть ссылка на первоисточник, ничего про лицензию там не пишут, и файлы в открытом доступе.

См. graphic gems 1 файл fitCurves.cpp и где то там же рисовалка для сплайнов. Ничего про лицензию внутри нет.

Вообще, я там достаточно много перекроил.

PS: Я еще один быстрый способ свертки совсем забыл упомянуть. Это свертка при помощи FFT. Делается так:

1) находим спектр картинки (преобразование Фурье).

2) находим спектр кривой, нарисованной на черном фоне, начинающейся из центра картинки.

3) перемножаем спектры.

4) проводим обратное преобразование Фурье.

Еще один плюс этого способа - отсутствие краевых эффектов.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Литература? С преобразований Фурье начинала, но для начала было слишком сложно разобраться, забросила. Может и правда, так как сейчас кривую надо параметризировать, пускать точку уже не по вектору, а по кривой

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Не нужна тут литература, хватит и документации openCV.

Это все очень просто делается.

см.

dft

mulSpectrums

в opencv - шной документации.

И вот тут посмотрите (примерно на середине): http://www.fmwconcepts.com/imagemagick/fourier_transforms/fourier.html

Но тут все-же не совсем то.

О нашел: смотрите по ссылке выше подзаголовки Ideal Defocus и Ideal Motion Blur.

Эти полосатые картинки и есть Фурье спектр ядра свертки, для дефокуса - круг, для motion blur - короткая прямая.

У Вас вместо белой точки будет Ваша кривая, перемножать надо не с изображением кривой, а с ее спектром.

  • Like 1

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Еще один плюс этого способа - отсутствие краевых эффектов.

При свёртке через фурье краевые эффекы будут. Просто они будут иметь другой характер.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Что то код с сайта плохо работает выдает только кусок изображения, не пойму где косяк.

post-1-0-51901700-1344506061_thumb.jpg

взял отсюда:

http://docs.opencv.org/modules/core/doc/operations_on_arrays.html?highlight=mulspectrums#dft

#include <iostream>
#include <vector>
#include <stdio.h>
#include <functional>
#include <algorithm>
#include <numeric>
#include <cstddef>
#include "opencv2/core/core.hpp"
#include "opencv2/core/gpumat.hpp"
#include "opencv2/core/opengl_interop.hpp"
#include "opencv2/gpu/gpu.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/contrib/contrib.hpp"
#include "opencv2/video/tracking.hpp"
#include "opencv2/imgproc/imgproc.hpp"
using namespace std;
using namespace cv;

void convolveDFT(Mat& A, Mat& B, Mat& C)
{
// reallocate the output array if needed
C.create(abs(A.rows - B.rows)+1, abs(A.cols - B.cols)+1, A.type());
Size dftSize;
// compute the size of DFT transform
dftSize.width = getOptimalDFTSize(A.cols + B.cols - 1);
dftSize.height = getOptimalDFTSize(A.rows + B.rows - 1);

// allocate temporary buffers and initialize them with 0's
Mat tempA(dftSize, A.type(), Scalar::all(0));
Mat tempB(dftSize, B.type(), Scalar::all(0));

// copy A and B to the top-left corners of tempA and tempB, respectively
Mat roiA(tempA, Rect(0,0,A.cols,A.rows));
A.copyTo(roiA);
Mat roiB(tempB, Rect(0,0,B.cols,B.rows));
B.copyTo(roiB);

// now transform the padded A & B in-place;
// use "nonzeroRows" hint for faster processing
dft(tempA, tempA, 0, A.rows);
dft(tempB, tempB, 0, B.rows);

// multiply the spectrums;
// the function handles packed spectrum representations well
mulSpectrums(tempA, tempB, tempA, 0);

// transform the product back from the frequency domain.
// Even though all the result rows will be non-zero,
// you need only the first C.rows of them, and thus you
// pass nonzeroRows == C.rows
dft(tempA, tempA, DFT_INVERSE + DFT_SCALE, A.rows);

// now copy the result back to C.
tempA(Rect(0, 0, C.cols, C.rows)).copyTo(C);

// all the temporary buffers will be deallocated automatically
}
// ---------------------------------
//
// ---------------------------------
int main( int argc, char** argv )
{
namedWindow("Image");
namedWindow("Kernel");
namedWindow("Result");
Mat Img=imread("C:\\ImagesForTest\\grid.png",0);
Img.convertTo(Img,CV_32FC1,1.0/255.0);
Mat kernel=imread("C:\\ImagesForTest\\Point.jpg",0);
kernel.convertTo(kernel,CV_32FC1,1.0/255.0);
int width=Img.cols;
int height=Img.rows;
Mat resim;

convolveDFT(kernel,Img, resim);

normalize(resim,resim,0,1,cv::NORM_MINMAX);
imshow("Kernel",kernel);
imshow("Image",Img);
imshow("Result",resim);
cvWaitKey(0);

}[/code]

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Поправил код, но краевые эффекты тут действительно проявляются не хуже чем при обычной обработке.

#include <iostream>
#include <vector>
#include <stdio.h>
#include <functional>
#include <algorithm>
#include <numeric>
#include <cstddef>
#include "opencv2/core/core.hpp"
#include "opencv2/core/gpumat.hpp"
#include "opencv2/core/opengl_interop.hpp"
#include "opencv2/gpu/gpu.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/contrib/contrib.hpp"
#include "opencv2/video/tracking.hpp"
#include "opencv2/imgproc/imgproc.hpp"
using namespace std;
using namespace cv;

void convolveDFT(Mat& A, Mat& B, Mat& C)
{
// reallocate the output array if needed
C.create(abs(A.rows - B.rows)+1, abs(A.cols - B.cols)+1, A.type());
Size dftSize;
// compute the size of DFT transform
dftSize.width = getOptimalDFTSize(A.cols + B.cols - 1);
dftSize.height = getOptimalDFTSize(A.rows + B.rows - 1);

// allocate temporary buffers and initialize them with 0's
Mat tempA(dftSize, A.type(), Scalar::all(0));
Mat tempB(dftSize, B.type(), Scalar::all(0));

// copy A and B to the top-left corners of tempA and tempB, respectively

Mat roiA(tempA, Rect(0,0,A.cols,A.rows));
A.copyTo(roiA);
Mat roiB(tempB, Rect(0,0,B.cols,B.rows));
B.copyTo(roiB);

// now transform the padded A & B in-place;
// use "nonzeroRows" hint for faster processing
dft(tempA, tempA,0,A.rows);
dft(tempB, tempB,0,A.rows);

// multiply the spectrums;
// the function handles packed spectrum representations well
mulSpectrums(tempA, tempB, tempA, 0);

// transform the product back from the frequency domain.
// Even though all the result rows will be non-zero,
// you need only the first C.rows of them, and thus you
// pass nonzeroRows == C.rows
dft(tempA, tempA, DFT_INVERSE + DFT_SCALE);

// now copy the result back to C.
C=tempA(Rect((dftSize.width-A.cols)/2,(dftSize.height-A.rows)/2,A.cols,A.rows)).clone();
// all the temporary buffers will be deallocated automatically
}
// ---------------------------------
//
// ---------------------------------
int main( int argc, char** argv )
{
namedWindow("Image");
namedWindow("Kernel");
namedWindow("Result");
Mat Img=imread("C:\\ImagesForTest\\grid.png",0);
Img.convertTo(Img,CV_32FC1,1.0/255.0);
Mat kernel=imread("C:\\ImagesForTest\\Point.jpg",0);
kernel.convertTo(kernel,CV_32FC1,1.0/255.0);
int width=Img.cols;
int height=Img.rows;
Mat resim;

convolveDFT(Img,kernel, resim);

normalize(resim,resim,0,1,cv::NORM_MINMAX);
imshow("Kernel",kernel);
imshow("Image",Img);
imshow("Result",resim);
cvWaitKey(0);

}[/code]

Ядро, кстати говоря, надо центровать по центру масс, иначе изображение едет (хотя х.з. тут эксперименты нужны).

Ключевая точка (якорь) здесь середина ядра, вот от этой точки и идет размазывание. Если сместим не туда, изображение съезжает, что и понятно, т.к. в точку якоря идут значения точек находящихся на расстоянии смещения нашей кривой от якоря.

post-1-0-60619100-1344507704_thumb.jpg

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Здравствуйте опять:) Сделала по сплайну, всё красиво, краевой исправила "на коленке" - дорисовала копимейкбордером и после применения свертки - кропнула)) задача теперь новая - добавить третью координату. То есть, фактически, при z>0 картинка "едет" на нас (увеличивается на каждом шаге свертки), в обратную - уменьшается. Вопрос опять таки в алгоритме. После каждого шага свертки увеличивить\уменьшать картинку? Или существует некий Vec4f?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Ну тут, если я правильно понял задачу, все достаточно просто.

Делаем набор изображений, по количеству равный желаемому ядру свертки, каждое из изображений увеличенное/уменьшенное и размытое по сплайну (но размер матрицы у всех одинаковый), находим взвешенную сумму (как раньше) только не между соседними пикселями одного изображения, а между пикселями с одинаковыми координатами в "стопке" изображений.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Это самый рациональный способ? Если я правильно поняла, время рассчета задачи увеличивается катастрофически (по сплайну и так получается около 40 секунд, за что меня все время пинают)

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Никуда от этого не деться, размерность задачи увеличивается на единицу - будьте добры увеличить на единицу показатель степени количества операций .

А что Фурье то не применяете для размыва по сплайну?

PS: Это релиз работает 40 секунд?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

А я перекрутила Безье по Вашей ссылке, там всё хорошо) сам сплайн строится мгновенно, а вот скорость блюра зависит от длины кривой, количества точек аппроксимации, шага свертки... Ну и качество пропорционально времени выходит. Повторю на всякий: свертку сделать двухмерную, потом размножить картинку н раз (по длине третьей координаты), каждый раз увеличивая и кропая. И потом еще раз произвести свертку, но уже по финальных картинках?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Дык Безье никуда не денется (кривая рисуется на ядре свертки (см.выше)), Фурье только саму свертку ускорит в количество раз пропорциональное длине ядра, для этого метода размер кривой не имеет значения.

А так, да все правильно, только уточню : последняя свертка выполняется вглубь (суммируются пиксели имеющие одинаковые координаты, но находящиеся на разных изображениях).

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Фурье падает на

mulSpectrums(tempA, tempB, tempA, 0);

в чем может быть причина?:(

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Вероятно в этом (перепутал я rows и cols)

mask.create(Mag.cols,Mag.rows,CV_32F);
Упс, это я про другой код :) У Вас, скорее всего тип данных не CV_32FC1, или размеры изображений не совпадают. Посмотрите в отладчике. Это не блюр (не в том виде котором Вам нужно, хотя отличается только ядром), но можно отсюда натащить кусков:
#include "stdafx.h"
#pragma once
#include <string>
#include <iostream>
using namespace std;
using namespace cv;
//----------------------------------------------------------
// Функция для перестановки четвертей изображения местамии
// так, чтобы ноль спектра находился в центре изображения.
//----------------------------------------------------------
void Recomb(Mat &src,Mat &dst)
{
int cx = src.cols>>1;
int cy = src.rows>>1;
Mat tmp;
tmp.create(src.size(),src.type());
src(Rect(0, 0, cx, cy)).copyTo(tmp(Rect(cx, cy, cx, cy)));
src(Rect(cx, cy, cx, cy)).copyTo(tmp(Rect(0, 0, cx, cy)));
src(Rect(cx, 0, cx, cy)).copyTo(tmp(Rect(0, cy, cx, cy)));
src(Rect(0, cy, cx, cy)).copyTo(tmp(Rect(cx, 0, cx, cy)));
dst=tmp;
}
//----------------------------------------------------------
// По заданному изображению рассчитывает
// действительную и мнимую части спектра Фурье
//----------------------------------------------------------
void ForwardFFT(Mat &Src, Mat *FImg)
{
int M = getOptimalDFTSize( Src.rows );
int N = getOptimalDFTSize( Src.cols );
Mat padded;
copyMakeBorder(Src, padded, 0, M - Src.rows, 0, N - Src.cols, BORDER_CONSTANT, Scalar::all(0));
// Создаем комплексное представление изображения
// planes[0] содержит само изображение, planes[1] его мнимую часть (заполнено нулями)
Mat planes[] = {Mat_<float>(padded), Mat::zeros(padded.size(), CV_32F)};
Mat complexImg;
merge(planes, 2, complexImg);
dft(complexImg, complexImg);
// После преобразования результат так-же состоит из действительной и мнимой части
split(complexImg, planes);

// обрежем спектр, если у него нечетное количество строк или столбцов
planes[0] = planes[0](Rect(0, 0, planes[0].cols & -2, planes[0].rows & -2));
planes[1] = planes[1](Rect(0, 0, planes[1].cols & -2, planes[1].rows & -2));

Recomb(planes[0],planes[0]);
Recomb(planes[1],planes[1]);
// Нормализуем спектр
planes[0]/=float(M*N);
planes[1]/=float(M*N);
FImg[0]=planes[0].clone();
FImg[1]=planes[1].clone();
}
//----------------------------------------------------------
// По заданным действительной и мнимой части
// спектра Фурье восстанавливает изображение
//----------------------------------------------------------
void InverseFFT(Mat *FImg,Mat &Dst)
{
Recomb(FImg[0],FImg[0]);
Recomb(FImg[1],FImg[1]);
Mat complexImg;
merge(FImg, 2, complexImg);
// Производим обратное преобразование Фурье
idft(complexImg, complexImg);
split(complexImg, FImg);
normalize(FImg[0], Dst, 0, 1, CV_MINMAX);
}
//----------------------------------------------------------
// Раскладывает изображение на амплитуду и фазу спектра Фурье
//----------------------------------------------------------
void ForwardFFT_Mag_Phase(Mat &src, Mat &Mag,Mat &Phase)
{
Mat planes[2];
ForwardFFT(src,planes);
Mag.zeros(planes[0].rows,planes[0].cols,CV_32F);
Phase.zeros(planes[0].rows,planes[0].cols,CV_32F);
cv::cartToPolar(planes[0],planes[1],Mag,Phase);
}
//----------------------------------------------------------
// По заданным амплитуде и фазе
// спектра Фурье восстанавливает изображение
//----------------------------------------------------------
void InverseFFT_Mag_Phase(Mat &Mag,Mat &Phase, Mat &dst)
{
Mat planes[2];
planes[0].create(Mag.rows,Mag.cols,CV_32F);
planes[1].create(Mag.rows,Mag.cols,CV_32F);
cv::polarToCart(Mag,Phase,planes[0],planes[1]);
InverseFFT(planes,dst);
}
//----------------------------------------------------------
// Точка входа
//----------------------------------------------------------
int _tmain(int argc, _TCHAR* argv[])
{
// Матрица изображения
Mat img;
// Ампльтуда спектра
Mat Mag;
// Фаза спектра
Mat Phase;
// Грузим изображение
img=imread("data/lena.bmp",0);
// Покажем размеры изображения
cout<<img.size().width<<endl;
cout<<img.size().height<<endl;

// Раскладываем изображение в спектр
ForwardFFT_Mag_Phase(img,Mag,Phase);

//----------------------------------------------------------
// Частотный фильтр
//----------------------------------------------------------
// нарисуем кольцо посередине
int R=100; // Внешний радиус кольца пропускания
int r=30; // Внутренний радиус кольца пропускания
Mat mask;
mask.create(Mag.rows,Mag.cols,CV_32F);
int cx = Mag.cols>>1;
int cy = Mag.rows>>1;
mask=1;
cv::circle(mask,cv::Point(cx,cy),R,CV_RGB(0,0,0),-1);
cv::circle(mask,cv::Point(cx,cy),r,CV_RGB(1,1,1),-1);
//mask=1-mask; // Раскомментировать для инверсии
cv::multiply(Mag,mask,Mag);
cv::multiply(Phase,mask,Phase);
//----------------------------------------------------------
// Обратное преобразование
//----------------------------------------------------------
InverseFFT_Mag_Phase(Mag,Phase,img);

//----------------------------------------------------------
// Вывод результатов
//----------------------------------------------------------
// Преобразуем к виду удобному для отображения в окне
Mat LogMag;
LogMag.zeros(Mag.rows,Mag.cols,CV_32F);
LogMag=(Mag+1);
cv::log(LogMag,LogMag);
//---------------------------------------------------
imshow("Логарифм амплитуды", LogMag);
imshow("Фаза", Phase);
imshow("Результат фильтрации", img);
//----------------------------------------------------------
// Ждем нажатия кнопки
//----------------------------------------------------------
cvWaitKey(0);
return 0;
}

[/code]

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

да я смотрю, что там нельзя будет разбить области видимости, точнее, прийдется разбивать на сегменты и сворачивать по их количеству, что впринципе и компенсирует выигранное время:( сижу читаю про потоки, так то всё готово, но дооолго

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Создайте учётную запись или войдите для комментирования

Вы должны быть пользователем, чтобы оставить комментарий

Создать учётную запись

Зарегистрируйтесь для создания учётной записи. Это просто!

Зарегистрировать учётную запись

Войти

Уже зарегистрированы? Войдите здесь.

Войти сейчас


  • Сейчас на странице   0 пользователей

    Нет пользователей, просматривающих эту страницу

×