Hugin trunk 0.1
Loading...
Searching...
No Matches
LensCalImageCtrl.cpp
Go to the documentation of this file.
1// -*- c-basic-offset: 4 -*-
2
11/* This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public
13 * License as published by the Free Software Foundation; either
14 * version 2 of the License, or (at your option) any later version.
15 *
16 * This software is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public
22 * License along with this software. If not, see
23 * <http://www.gnu.org/licenses/>.
24 *
25 */
26
27#include "panoinc_WX.h"
28#include "panoinc.h"
29#include "base_wx/platform.h"
30#include "LensCalImageCtrl.h"
31#include "vigra/transformimage.hxx"
33#include "nona/ImageRemapper.h"
34#include "LensCalApp.h"
35#include "base_wx/wxcms.h"
36
37// init some values
63
68
70{
72 {
73 return;
74 };
75 vigra::Point2D pos(e.GetPosition().x,e.GetPosition().y);
77 if(lines.empty())
78 return;
79 int found_line=-1;
81 {
84 double x;
85 double y;
86 if(!trans.transformImgCoord(x,y,pos.x,pos.y))
87 return;
88 pos.x=x;
89 pos.y=y;
90 }
91 else
92 {
95 };
96
97 //find line which is nearest the clicked position
98 std::vector<double> min_distance(lines.size(),10000);
99 double shortest_distance=10000;
100 for(unsigned int i=0;i<lines.size();i++)
101 {
103 {
104 for(unsigned int j=0;j<lines[i].line.size();j++)
105 {
106 double distance=(lines[i].line[j]-pos).magnitude();
107 if(distance<min_distance[i])
108 min_distance[i]=distance;
109 };
110 };
112 {
114 if(shortest_distance<50)
115 {
117 };
118 };
119 };
120 if(found_line==-1)
121 {
122 return;
123 };
124 if(e.LeftIsDown())
125 {
127 }
128 else
129 {
131 };
133 wxGetApp().GetLensCalFrame()->UpdateListString(m_imageIndex);
134 DrawView();
135 Refresh();
136};
137
139{
140 if(m_imageLines==NULL)
141 return;
143 {
144 m_display_img.Create(m_remapped_img.GetWidth(), m_remapped_img.GetHeight());
145 }
146 else
147 {
148 m_display_img.Create(m_scaled_img.GetWidth(), m_scaled_img.GetHeight());
149 };
152 // copy resized image into buffer
154 {
156 memDC.DrawBitmap(m_remapped_img,0,0,false);
157 }
158 else
159 {
160 memDC.DrawBitmap(m_scaled_img,0,0,false);
161 };
162 if(m_showLines)
163 {
165 for(unsigned int i=0;i<lines.size();i++)
166 {
167 if(lines[i].line.size()<2)
168 continue;
169 switch(lines[i].status)
170 {
172 memDC.SetPen(wxPen(wxColour(0,255,0), 1, wxPENSTYLE_SOLID));
173 break;
175 memDC.SetPen(wxPen(wxColour(255, 0, 0), 1, wxPENSTYLE_SOLID));
176 break;
177 default:
178 memDC.SetPen(wxPen(wxColour(128, 128, 128), 1, wxPENSTYLE_SOLID));
179 break;
180 };
181 for(unsigned int j=0;j<lines[i].line.size()-1;j++)
182 {
183 int x1,y1,x2,y2;
185 {
186 double x,y;
187 if(!trans.transformImgCoord(x,y,lines[i].line[j].x,lines[i].line[j].y))
188 continue;
191 if(!trans.transformImgCoord(x,y,lines[i].line[j+1].x,lines[i].line[j+1].y))
192 continue;
195 }
196 else
197 {
198 x1=hugin_utils::roundi(m_scale*lines[i].line[j].x);
199 y1=hugin_utils::roundi(m_scale*lines[i].line[j].y);
200 x2=hugin_utils::roundi(m_scale*lines[i].line[j+1].x);
201 y2=hugin_utils::roundi(m_scale*lines[i].line[j+1].y);
202 };
203 memDC.DrawLine(x1,y1,x2,y2);
204 };
205 };
206 };
207 memDC.SelectObject(wxNullBitmap);
208};
209
211{
212 if(m_imageLines==NULL || !m_img.Ok() || (m_previewMode==mode_edge && !m_edge.Ok()))
213 {
216 Refresh(true);
217 return;
218 }
219 int x = GetSize().x;
220 int y = GetSize().y;
221 // scale to fit the window
222 int new_width;
223 int new_height;
224
225 float r_img = (float)m_img.GetWidth() / (float)m_img.GetHeight();
226 float r_window = (float)x/(float)y;
227 if ( r_img > r_window )
228 {
229 m_scale = (float)x / m_img.GetWidth();
230 new_width = x;
232 }
233 else
234 {
235 m_scale = (float)y / m_img.GetHeight();
236 new_height = y;
238 }
239 switch(m_previewMode)
240 {
241 case mode_original:
243 break;
244 case mode_edge:
246 break;
247 case mode_corrected:
249 break;
250 };
251 // draw new view into offscreen buffer
252 DrawView();
253 // eventually update the view
254 Refresh(false);
255};
256
257// Define the repainting behaviour
259{
260 wxPaintDC paintDC(this);
261#ifdef __WXGTK3__
262 // wxGTK3 prints an assert when trying to draw empty bitmap, Ok() is returning true in this case
263 // so check also bitmap dimensions
264 if (m_display_img.Ok() && m_display_img.GetWidth() > 0 && m_display_img.GetHeight() > 0)
265#else
266 if ( m_display_img.Ok() )
267#endif
268 {
269 paintDC.DrawBitmap(m_display_img, 0,0, FALSE);
270 }
271}
272
274{
277 std::string filename(newList->GetFilename().mb_str(HUGIN_CONV_FILENAME));
278 ImageCache::EntryPtr img = ImageCache::getInstance().getImage(filename);
279 // we need to create a copy, otherwise the color management function will modifiy the image
280 // directly in the ImageCache
281 m_img = imageCacheEntry2wxImage(img).Copy();
282 if (!img->iccProfile->empty() || m_hasMonitorProfile)
283 {
285 }
286 SetEdgeImage();
287
288 wxSizeEvent e;
289 Resize (e);
290}
291
293{
295 m_img.Create(0,0,true);
296 m_edge.Create(0,0,true);
297 m_remapped_img.Create(0,0,true);
298
299 wxSizeEvent e;
300 Resize(e);
301};
302
304{
306 // draw new view into offscreen buffer
307 DrawView();
308 // eventually update the view
309 Refresh(false);
310};
311
313{
315 wxSizeEvent e;
316 Resize (e);
317 Refresh(true);
318};
319
326
327void LensCalImageCtrl::SetLensDistortions(const double newA, const double newB, const double newC, const double newD, const double newE)
328{
329 m_a=newA;
330 m_b=newB;
331 m_c=newC;
332 m_d=newD;
333 m_e=newE;
335 {
336 wxSizeEvent e;
337 Resize(e);
338 };
339};
340
341vigra::RGBValue<vigra::UInt8> gray2RGB(vigra::UInt8 const& v)
342{
343 return vigra::RGBValue<vigra::UInt8>(v,v,v);
344}
345
347{
348 vigra::BImage* edgeImage=m_imageLines->GetEdgeImage();
349 if(edgeImage->width()>0 && edgeImage->height()>0)
350 {
351 // we need to convert to RGB
352 m_edgeImage.resize(edgeImage->width(),edgeImage->height());
353 vigra::transformImage(srcImageRange(*edgeImage), destImage(m_edgeImage), &gray2RGB);
354 m_edge.SetData((unsigned char*)m_edgeImage.data(),m_edgeImage.width(),m_edgeImage.height(),true);
355 }
356 else
357 {
358 m_edgeImage.resize(0,0);
359 m_edge.Create(0,0,true);
360 };
361 wxSizeEvent e;
362 Resize(e);
363};
364
365void LensCalImageCtrl::GenerateRemappedImage(const unsigned int newWidth,const unsigned int newHeight)
366{
368 //generate SrcPanoImage with current settings
370 m_panoimage.setProjection(m_projection);
371 m_panoimage.setExifFocalLength(m_focallength);
372 m_panoimage.setCropFactor(m_cropfactor);
373 m_panoimage.setExposureValue(0);
379 double hfov=HuginBase::SrcPanoImage::calcHFOV(m_panoimage.getProjection(),m_panoimage.getExifFocalLength(),m_panoimage.getCropFactor(),m_panoimage.getSize());
380 m_panoimage.setHFOV(hfov);
381
382 std::string filename(m_imageLines->GetFilename().mb_str(HUGIN_CONV_FILENAME));
383 ImageCache::EntryPtr img = ImageCache::getInstance().getImage(filename);
384 //fill options with current settings
385 switch(m_projection)
386 {
389 break;
392 break;
396 break;
399 break;
402 break;
405 break;
408 break;
411 break;
412 };
414 m_opts.setWidth(newWidth,false);
415 m_opts.setHFOV(m_panoimage.getHFOV(),false);
416 m_opts.setROI(vigra::Rect2D(0,0,m_opts.getWidth(),m_opts.getHeight()));
417 //now remap image
418 remapped->setPanoImage(m_panoimage,m_opts, m_opts.getROI());
419 remapped->remapImage(vigra::srcImageRange(*(img->get8BitImage())),vigra_ext::INTERP_CUBIC, wxGetApp().GetLensCalFrame());
420 m_remappedImage=remapped->m_image;
421 m_remapped_img.SetData((unsigned char*)m_remappedImage.data(),m_remappedImage.width(),m_remappedImage.height(),true);
422 // apply color profiles
423 if (!img->iccProfile->empty() || m_hasMonitorProfile)
424 {
426 }
427 delete remapped;
428};
429
430IMPLEMENT_DYNAMIC_CLASS(LensCalImageCtrl, wxPanel)
431
433{
435}
436
438{
440 cp->Create(m_parentAsWindow, GetID(), GetPosition(), GetSize(), GetStyle("style"), GetName());
442 return cp;
443}
444
446{
447 return IsOfClass(node, "LensCalCanvas");
448}
449
450IMPLEMENT_DYNAMIC_CLASS(LensCalImageCtrlXmlHandler, wxXmlResourceHandler)
declaration of application class for lens calibrate application
vigra::RGBValue< vigra::UInt8 > gray2RGB(vigra::UInt8 const &v)
declaration of preview for lens calibration gui
Contains functions to transform whole images.
struct to hold a image state for stitching
Holds transformations for Image -> Pano and the other way.
void createTransform(const vigra::Diff2D &srcSize, VariableMap srcVars, Lens::LensProjectionFormat srcProj, const vigra::Diff2D &destSize, PanoramaOptions::ProjectionFormat destProj, const std::vector< double > &destProjParam, double destHFOV, const vigra::Diff2D &origSrcSize)
initialize pano->image transformation
void createInvTransform(const vigra::Diff2D &srcSize, VariableMap srcVars, Lens::LensProjectionFormat srcProj, const vigra::Diff2D &destSize, PanoramaOptions::ProjectionFormat destProj, const std::vector< double > &destProjParam, double destHFOV, const vigra::Diff2D &origSrcSize)
create image->pano transformation
void setHFOV(double h, bool keepView=true)
set the horizontal field of view.
void setProjection(ProjectionFormat f)
set the Projection format and adjust the hfov/vfov if nessecary
void setHeight(unsigned int h)
set panorama height
const vigra::Rect2D & getROI() const
void setWidth(unsigned int w, bool keepView=true)
set panorama width keep the HFOV, if keepView=true
void setROI(const vigra::Rect2D &val)
unsigned int getWidth() const
unsigned int getHeight() const
get panorama height
void setVar(const std::string &name, double val)
static double calcHFOV(SrcPanoImage::Projection proj, double fl, double crop, vigra::Size2D imageSize)
calculate hfov of an image given focal length, image size and crop factor
HuginBase::SrcPanoImage * GetPanoImage()
return the SrcPanoImage from the given filename
vigra::BImage * GetEdgeImage()
return pointer to edge image
const wxString GetFilename()
returns the filename
void SetLines(HuginLines::Lines lines)
store given lines in member variable
const HuginLines::Lines GetLines()
returns the list of detected lines
xrc handler for LensCalImageCtrl
virtual bool CanHandle(wxXmlNode *node)
virtual wxObject * DoCreateResource()
image previewer for lens calibration GUI
LensCalPreviewMode m_previewMode
which image should be drawn
void SetShowLines(bool showLines)
void DrawView()
draw the view into the offscreen buffer
void SetMode(const LensCalPreviewMode newMode)
set which image (original, edge, remapped/corrected) should be drawn
LensCalImageCtrl()
constructor
wxBitmap m_scaled_img
the scaled image to save resizing
wxImage m_img
the image to adjust (full scale)
HuginBase::PanoramaOptions m_opts
HuginBase::SrcPanoImage::Projection m_projection
void SetLensDistortions(const double newA, const double newB, const double newC, const double newD, const double newE)
updates the internal values of the lens distortions parameters (needed only for remapped image)
void OnPaint(wxPaintEvent &dc)
paint event
HuginBase::SrcPanoImage m_panoimage
wxBitmap m_display_img
the image to display, e.g.
float m_scale
scale factor for scaling from m_img to m_scaled_img
void SetLens(const HuginBase::SrcPanoImage::Projection newProjection, const double newFocallength, const double newCropfactor)
updates the internal values of the lens (needed only for remapped image)
cmsHPROFILE m_monitorProfile
monitor profile
wxImage m_remapped_img
the remapped image as wxImage
vigra::BRGBImage m_edgeImage
the edge image as RGBImage (in m_imageLines the edge image is grayscale (vigra::BImage))
unsigned int m_imageIndex
const LensCalPreviewMode GetMode()
return actual preview mode
void SetEdgeImage()
converts the edge image into wxImage
vigra::BRGBImage m_remappedImage
the remapped image
void Resize(wxSizeEvent &e)
resize event, recalculates the offscreen buffer
void SetImage(ImageLineList *newList, unsigned int newIndex)
set preview setting to given ImageLineList
ImageLineList * m_imageLines
struct with filename, edge image and detected lines
void SetEmptyImage()
set preview to empty image
void OnMouseEvent(wxMouseEvent &e)
void GenerateRemappedImage(const unsigned int newWidth, const unsigned int newHeight)
generates the remapped image suitable for wxImage
bool m_hasMonitorProfile
true, if we found a real monitor profile
wxImage m_edge
the edge detect image (resized scale)
bool m_showLines
true, if the lines should be drawn above the image
implementation of huginApp Class
#define HUGIN_CONV_FILENAME
Definition platform.h:40
void CorrectImage(wxImage &image, const vigra::ImageImportInfo::ICCProfile &iccProfile, const cmsHPROFILE &monitorProfile)
apply color correction to given image using input iccProfile and monitor profile
Definition wxcms.cpp:218
void GetMonitorProfile(wxString &profileName, cmsHPROFILE &profile)
retrieve monitor profile from system
Definition wxcms.cpp:201
@ valid_line_disabled
Definition LinesTypes.h:36
std::vector< SingleLine > Lines
vector of extracted lines from image
Definition LinesTypes.h:50
int roundi(T x)
Definition hugin_math.h:73
include file for the hugin project
include file for the hugin project
std::vector< deghosting::BImagePtr > threshold(const std::vector< deghosting::FImagePtr > &inputImages, const double threshold, const uint16_t flags)
Threshold function used for creating alpha masks for images.
Definition threshold.h:41
wxImage imageCacheEntry2wxImage(ImageCache::EntryPtr e)