2 * psychlops_figure_gabor.cpp
3 * Psychlops Standard Library (Universal)
5 * Last Modified 2006/01/19 by Kenchi HOSOKAWA
6 * (C) 2006 Kenchi HOSOKAWA, Kazushi MARUYA and Takao SATO
14 #include "../../../platform/gl/psychlops_g_GL_h.h"
16 #include "../../../psychlops_core.h"
17 #include "psychlops_figure_gabor.h"
23 double bellcurve(const double x, const double sigma) {
24 return exp( -(x*x) / (2.0*sigma*sigma) );
28 namespace StimulusTemplate {
32 Gabor& Gabor::setContrast(double cont) {
36 Gabor& Gabor::setWavelength(Length length) {
40 Gabor& Gabor::setOrientation(Angle orient) {
44 Gabor& Gabor::setPhase(Angle phs) {
48 const Point Gabor::getDatum() const {
49 Point p(left_+width_/2.0, top_+height_/2.0);
57 int substructImages(Image &result, const Image &s1, const Image &s2, const double factor)
59 if(s1.getHeight()!=s2.getHeight()) throw new Exception("substructImages");
60 if(s1.getWidth()!=s2.getWidth()) throw new Exception("substructImages");
62 result.set(s1.getWidth(), s1.getHeight());
64 double difference = 0, sum = 0;
65 bool error = false, serror = false;
66 for(int y=0; y<s1.getHeight(); y++) {
67 for(int x=0; x<s1.getWidth(); x++) {
70 difference = c1.getR()-c2.getR();
71 sum += difference!=0.0 ? 1 : 0;
72 error = difference>=2.0/255.0;
73 serror = serror || error;
74 result.pix_raw(x,y,Color(
76 difference>0 ? factor*difference : 0,
77 difference<0 ? factor*difference : 0,
78 //c2.getR()-c1.getR()> 0 ? factor*(c2.getR()-c1.getR()) : 0,//.5 + factor * (c1.getR() - c2.getR()),
79 //c1.getR()-c2.getR()> 0 ? factor*(c1.getR()-c2.getR()) : 0,//.5 + factor * (c1.getG() - c2.getG()),
80 0,//.5 + factor * (c1.getB() - c2.getB()),
83 //if(c1.getR()-c2.getR()>0.01) std::cout << c1.getR()-c2.getR() << " " << c1.getR() << " " << c2.getR() << std::endl;
86 return serror ? -sum : sum;
89 void drawImageCoordinateTuner(Image &img)
91 const int width=256, height=256;
93 img.set(width, height);
94 for(int y=0; y<height; y++) {
95 for(int x=0; x<width; x++) {
97 Color(abs(x-127.5)/255.0, 0.0, 0.0)
102 void drawGrating(Image &img, int width , int height, double wavelength, double contrast, double orientation, double phase)
105 img.set(width, height);
106 double xp, yp, r, freq = (1.0/wavelength)*2*PI;
107 for(int y=0; y<height; y++) {
109 for(int x=0; x<width; x++) {
111 r = sqrt(xp*xp+yp*yp);
114 0.5+0.5 * contrast* cos(freq* (sin(orientation)*xp-cos(orientation)*yp) + phase)
120 void drawGaussian(Image &img, double sigma, double factor)
123 img.set(sigma*8, sigma*8);
124 const int width = img.getWidth(), height = img.getHeight();
125 double xp, yp, r, r2;
126 for(int y=0; y<height; y++) {
128 for(int x=0; x<width; x++) {
130 r = sqrt(xp*xp+yp*yp);
131 r2 = -(r*r) / (2.0*sigma*sigma);
132 img.pix_raw(x,y,Color(factor*(exp(r2))));
136 void drawGabor(Image &img, double sigma, double wavelength, double contrast, double orientation, double phase)
139 img.set(sigma*8, sigma*8);
140 const int width = img.getWidth(), height = img.getHeight();
141 double xp, yp, r, freq = (1.0/wavelength)*2*PI;
142 for(int y=0; y<height; y++) {
144 for(int x=0; x<width; x++) {
146 r = sqrt(xp*xp+yp*yp);
149 0.5+0.5 * contrast* cos(freq* (sin(orientation)*xp-cos(orientation)*yp) + phase)
150 * exp( -(r*r) / (2.0*sigma*sigma) ))
159 GaborBase::GaborBase()
168 GaborBase& GaborBase::setSigma(double sigma)
170 return setSigma(sigma*pixel);
172 GaborBase& GaborBase::setSigma(Length sigma)
174 Rectangle::set(sigma*8.0, sigma*8.0);
177 GaborBase& GaborBase::setWave(double wavelen, double cont, double orient, double phs)
179 return setWave(wavelen*pixel, cont, orient*degree, phs*degree);
181 GaborBase& GaborBase::setWave(Length wavelen, double cont, Angle orient, Angle phs)
184 wavelength = wavelen;
185 orientation = orient;
191 const bool ImageGabor::Key::operator <(Key rhs) const
193 for(int i=0; i<5; i++)
195 if(data[i]!=rhs.data[i]) return data[i]<rhs.data[i];
199 const bool ImageGabor::Key::operator >(Key rhs) const
201 for(int i=0; i<5; i++)
203 if(data[i]!=rhs.data[i]) return data[i]>rhs.data[i];
209 ImageGabor::ImageGabor() : GaborBase()
213 ImageGabor& ImageGabor::cache(DrawableWithCache &target)
215 Image* tmp = new Image();
216 Figures::drawGabor(*tmp, this->getWidth()/8.0, 1.0/wavelength, contrast, orientation, phase);
219 key.data[0] = this->getWidth();
220 key.data[1] = wavelength;
221 key.data[2] = contrast;
222 key.data[3] = orientation;
224 cache_list[key] = tmp;
228 ImageGabor& ImageGabor::draw(Drawable &target)
231 key.data[0] = this->getWidth();
232 key.data[1] = wavelength;
233 key.data[2] = contrast;
234 key.data[3] = orientation;
236 if(cache_list.count(key)!=0) {
237 cache_list[key]->centering(this->getCenter()).draw();
239 Figures::drawGabor(normal_, this->getWidth()/8.0, 1.0/wavelength, contrast, orientation, phase);
240 normal_.centering(this->getCenter()).draw();
245 void ImageGabor::to(Image &dest, Canvas &media)
247 Figures::drawGabor(dest, this->getWidth()/8.0, 1.0/wavelength, contrast, orientation, phase);
256 QuickGabor::Instance::Instance() : instantiated(false) {
257 referenced_count_ = 0;
259 QuickGabor::Instance::~Instance() {
261 void QuickGabor::Instance::release() {
263 if(referenced_count_<=0) {
268 instantiated = false;
271 void QuickGabor::Instance::set(double sigma) {
273 size_ = (int)(sigma_*6.0);
278 void QuickGabor::Instance::setEnvelope() {
281 envelope_ = new Image;
282 envelope_->set(size_, size_, Image::RGBA, Image::FLOAT);
283 int halfsize = size_/2;
285 if(halfsize*2 != size_) particle = 1;
286 for(int y=-halfsize; y<halfsize+particle; y++) {
287 for(int x=-halfsize; x<halfsize+particle; x++) {
288 //col.set( 0.5, 0.5, 0.5, 1-bellcurve(sqrt(x*x+y*y), sigma_) );
289 envelope_->pix(x+halfsize, y+halfsize, Color::gray);
290 envelope_->alpha(x+halfsize, y+halfsize, 1-bellcurve(::sqrt((double)(x*x+y*y)), sigma_));
295 void QuickGabor::Instance::setCarrier() {
296 double height, halfwidth;
297 carrier_ = new Rectangle[size_];
298 for(int x=1; x<size_-1; x++) {
299 halfwidth = size_/2-1;
300 height = 2*sqrt(halfwidth*halfwidth-(x-halfwidth)*(x-halfwidth));
301 carrier_[x].set(1.1,height).shift(x-halfwidth-0.5,-height/2);
304 QuickGabor::Instance& QuickGabor::Instance::draw(int x, int y, Length wavelength, Angle orientation, Angle phase, double contrast, Drawable &target) {
306 int limit = size_/2 -1;
308 // glEnable(GL_LINE_SMOOTH);
309 // glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
310 glTranslated(x+limit,y+limit,0);
311 glRotated(orientation,0,0,1);
312 for(int i=1; i<size_-3; i++) {
314 sin( ((double)i/(double)wavelength)*2*PI + phase.at_radian() )
316 carrier_[i].draw(col, target);
319 envelope_->draw(x,y,target);
325 std::vector<QuickGabor::Instance *> QuickGabor::instance_;
326 int QuickGabor::setInstance(double sigma) {
330 if(instance_.empty()) {
331 // instance_ = std::vector<Instance>();
333 for(std::vector<Instance *>::iterator iter=instance_.begin(); iter!=instance_.end(); iter++, index++) {
334 if((*iter)->sigma_ == sigma) {
335 (*iter)->referenced_count_++;
346 instance_.push_back( ins );
347 instance_.back()->referenced_count_++;
353 void QuickGabor::release() {
354 if(sigma_index_>=0 && sigma_index_<instance_.size()) instance_[sigma_index_]->release();
359 QuickGabor::QuickGabor() {
361 QuickGabor::QuickGabor(double length, double sigma, double cont, double orient, double phs) {
362 set(length, sigma, cont, orient, phs);
364 QuickGabor::QuickGabor(Length length, Length sigma, double cont, Angle orient, Angle phs) {
365 set(length, sigma, cont, orient, phs);
367 QuickGabor::~QuickGabor() {
370 QuickGabor & QuickGabor::set(double length, double sigma, double cont, double orient, double phs) {
371 return set(length*pixel, sigma*pixel, cont, orient*degree, phs*degree);
373 QuickGabor & QuickGabor::set(Length length, Length sigma, double cont, Angle orient, Angle phs) {
377 orientation = orient;
382 width_ = (int)(sigma_*6.0);
385 sigma_index_ = setInstance(sigma_);
389 QuickGabor & QuickGabor::setDatum(const Point &po) {
390 return centering(po);
392 QuickGabor & QuickGabor::shift(const double x, const double y, const double z) {
397 QuickGabor & QuickGabor::centering(const double x, const double y, const double z) {
398 left_ = x - width_/2.0;
399 top_ = y - height_/2.0;
402 QuickGabor & QuickGabor::centering(const Point &po) {
403 return centering(po.x, po.y);
405 QuickGabor & QuickGabor::centering(const Drawable &target) {
406 return centering(Display::getCenter());
409 QuickGabor & QuickGabor::draw(Drawable &target) {
410 instance_[sigma_index_]->draw((int)left_, (int)top_, wavelength, orientation, phase, contrast, target);
413 QuickGabor & QuickGabor::draw(int x, int y, Drawable &target) {
414 instance_[sigma_index_]->draw(x, y, wavelength, orientation, phase, contrast, target);