Commit fcddfa4f authored by Cartucho's avatar Cartucho Committed by Maksim Shabunin

GSoC 2016 - Adding ALIASES for tutorial (#7041)

* GSoC 2016 - Adding toggle files to be used by tutorials.

Add a toggle option for tutorials.
* adds a button on the HTML tutorial pages to switch between blocks
* the default option is for languages: one can write a block
for C++ and another one for Python without re-writing the tutorial

Add aliases to the doxyfile.
* adding alises to make a link to previous and next tutorial.
* adding alias to specify the toggle options in the tutorials index.
* adding alias to add a youtube video directly from link.

Add a sample tutorial (mat_mask_opertaions) using the developed aliases:
* youtube alias
* previous and next tutorial alias
* buttons
* languages info for tutorial table of content
* code referances with snippets (and associated sample code files)

* Removing the automatic ordering.
Adding specific toggles for cpp, java and python.
Move all the code to the footer / header and Doxyfile.
Updating documentation.
parent 36b5abf6
...@@ -31,10 +31,17 @@ MULTILINE_CPP_IS_BRIEF = NO ...@@ -31,10 +31,17 @@ MULTILINE_CPP_IS_BRIEF = NO
INHERIT_DOCS = YES INHERIT_DOCS = YES
SEPARATE_MEMBER_PAGES = NO SEPARATE_MEMBER_PAGES = NO
TAB_SIZE = 4 TAB_SIZE = 4
ALIASES = ALIASES += add_toggle{1}="@htmlonly[block] <div class='newInnerHTML'>\1</div><div> <script type="text/javascript"> addToggle(); </script>@endhtmlonly"
ALIASES += add_toggle_cpp="@htmlonly[block] <div class='newInnerHTML' title='cpp' style='display: none;'>C++</div><div class='toggleable_div label_cpp' style='display: none;'>@endhtmlonly"
ALIASES += add_toggle_java="@htmlonly[block] <div class='newInnerHTML' title='java' style='display: none;'>Java</div><div class='toggleable_div label_java' style='display: none;'>@endhtmlonly"
ALIASES += add_toggle_python="@htmlonly[block] <div class='newInnerHTML' title='python' style='display: none;'>Python</div><div class='toggleable_div label_python' style='display: none;'>@endhtmlonly"
ALIASES += end_toggle="@htmlonly[block] </div> @endhtmlonly"
ALIASES += prev_tutorial{1}="**Prev Tutorial:** \ref \1 \n"
ALIASES += next_tutorial{1}="**Next Tutorial:** \ref \1 \n"
ALIASES += youtube{1}="@htmlonly[block]<div align='center'><iframe title='my title' width='560' height='349' src='http://www.youtube.com/embed/\1?rel=0' frameborder='0' align='middle' allowfullscreen></iframe></div>@endhtmlonly"
TCL_SUBST = TCL_SUBST =
OPTIMIZE_OUTPUT_FOR_C = NO OPTIMIZE_OUTPUT_FOR_C = NO
OPTIMIZE_OUTPUT_JAVA = NO OPTIMIZE_OUTPUT_JAVA = YES
OPTIMIZE_FOR_FORTRAN = NO OPTIMIZE_FOR_FORTRAN = NO
OPTIMIZE_OUTPUT_VHDL = NO OPTIMIZE_OUTPUT_VHDL = NO
EXTENSION_MAPPING = EXTENSION_MAPPING =
......
...@@ -17,5 +17,74 @@ $generatedby &#160;<a href="http://www.doxygen.org/index.html"> ...@@ -17,5 +17,74 @@ $generatedby &#160;<a href="http://www.doxygen.org/index.html">
</a> $doxygenversion </a> $doxygenversion
</small></address> </small></address>
<!--END !GENERATE_TREEVIEW--> <!--END !GENERATE_TREEVIEW-->
<script type="text/javascript">
//<![CDATA[
function addButton(label, buttonName) {
var b = document.createElement("BUTTON");
b.innerHTML = buttonName;
b.setAttribute('class', 'toggleable_button label_' + label);
b.onclick = function() {
$('.toggleable_button').css({
border: '2px outset',
'border-radius': '4px'
});
$('.toggleable_button.label_' + label).css({
border: '2px inset',
'border-radius': '4px'
});
$('.toggleable_div').css('display', 'none');
$('.toggleable_div.label_' + label).css('display', 'block');
};
b.style.border = '2px outset';
b.style.borderRadius = '4px';
b.style.margin = '2px';
return b;
}
function buttonsToAdd($elements, $heading, $type) {
if ($elements.length === 0) {
$elements = $("" + $type + ":contains(" + $heading.html() + ")").parent().prev("div.newInnerHTML");
}
var arr = jQuery.makeArray($elements);
var seen = {};
arr.forEach(function(e) {
var txt = e.innerHTML;
if (!seen[txt]) {
$button = addButton(e.title, txt);
if (Object.keys(seen).length == 0) {
var linebreak1 = document.createElement("br");
var linebreak2 = document.createElement("br");
($heading).append(linebreak1);
($heading).append(linebreak2);
}
($heading).append($button);
seen[txt] = true;
}
});
return;
}
$("h2").each(function() {
$heading = $(this);
$smallerHeadings = $(this).nextUntil("h2").filter("h3").add($(this).nextUntil("h2").find("h3"));
if ($smallerHeadings.length) {
$smallerHeadings.each(function() {
var $elements = $(this).nextUntil("h3").filter("div.newInnerHTML");
buttonsToAdd($elements, $(this), "h3");
});
} else {
var $elements = $(this).nextUntil("h2").filter("div.newInnerHTML");
buttonsToAdd($elements, $heading, "h2");
}
});
$(".toggleable_button").first().click();
var $clickDefault = $('.toggleable_button.label_python').first();
if ($clickDefault.length) {
$clickDefault.click();
}
$clickDefault = $('.toggleable_button.label_cpp').first();
if ($clickDefault.length) {
$clickDefault.click();
}
//]]>
</script>
</body> </body>
</html> </html>
...@@ -54,4 +54,34 @@ $extrastylesheet ...@@ -54,4 +54,34 @@ $extrastylesheet
</table> </table>
</div> </div>
<!--END TITLEAREA--> <!--END TITLEAREA-->
<script type="text/javascript">
//<![CDATA[
function getLabelName(innerHTML) {
var str = innerHTML.toLowerCase();
// Replace all '+' with 'p'
str = str.split('+').join('p');
// Replace all ' ' with '_'
str = str.split(' ').join('_');
// Replace all '#' with 'sharp'
str = str.split('#').join('sharp');
// Replace other special characters with 'ascii' + code
for (var i = 0; i < str.length; i++) {
var charCode = str.charCodeAt(i);
if (!(charCode == 95 || (charCode > 96 && charCode < 123) || (charCode > 47 && charCode < 58)))
str = str.substr(0, i) + 'ascii' + charCode + str.substr(i + 1);
}
return str;
}
function addToggle() {
var $getDiv = $('div.newInnerHTML').last();
var buttonName = $getDiv.html();
var label = getLabelName(buttonName.trim());
$getDiv.attr("title", label);
$getDiv.hide();
$getDiv = $getDiv.next();
$getDiv.attr("class", "toggleable_div label_" + label);
$getDiv.hide();
}
//]]>
</script>
<!-- end header part --> <!-- end header part -->
//<![CDATA[
MathJax.Hub.Config( MathJax.Hub.Config(
{ {
TeX: { TeX: {
...@@ -15,3 +15,4 @@ MathJax.Hub.Config( ...@@ -15,3 +15,4 @@ MathJax.Hub.Config(
} }
} }
); );
//]]>
...@@ -25,6 +25,8 @@ understanding how to manipulate the images on a pixel level. ...@@ -25,6 +25,8 @@ understanding how to manipulate the images on a pixel level.
- @subpage tutorial_mat_mask_operations - @subpage tutorial_mat_mask_operations
*Languages:* C++, Java, Python
*Compatibility:* \> OpenCV 2.0 *Compatibility:* \> OpenCV 2.0
*Author:* Bernát Gábor *Author:* Bernát Gábor
......
...@@ -439,6 +439,83 @@ Then include this snippet into documentation: ...@@ -439,6 +439,83 @@ Then include this snippet into documentation:
compatibility with the old rST documentation. But newly created samples should be included with the compatibility with the old rST documentation. But newly created samples should be included with the
_snippet_ command, since this method is less affected by the changes in processed file. _snippet_ command, since this method is less affected by the changes in processed file.
### Toggle buttons inclusion commands {#tutorial_documentation_toggle_buttons_commands_include}
Toggle buttons are used to display the selected configuration (e.g. programming language, OS, IDE).
To use the buttons in documentation, _add_toggle_ and _end_toggle_ commands are used.
The command _add_toggle_ can be
- general: _add_toggle{Button Name}_
- for C++: _add_toggle_cpp_
- for Java: _add_toggle_java_
- for Python: _add_toggle_python_
Example:
@verbatim
@add_toggle{Button Name}
text / code / doxygen commands
@end_toggle
@endverbatim
For example using toggle buttons with text and [code](@ref tutorial_documentation_commands_include) snippets:
@verbatim
### Buttons Example
@add_toggle_cpp
Text for C++ button
@snippet samples/cpp/tutorial_code/introduction/documentation/documentation.cpp hello_world
@end_toggle
@add_toggle_java
Text for Java button
@snippet samples/java/tutorial_code/introduction/documentation/Documentation.java hello_world
@end_toggle
@add_toggle_python
Text for Python button
@snippet samples/python/tutorial_code/introduction/documentation/documentation.py hello_world
@end_toggle
@endverbatim
Result looks like this:
### Buttons Example
@add_toggle_cpp
Text for C++ button
@snippet samples/cpp/tutorial_code/introduction/documentation/documentation.cpp hello_world
@end_toggle
@add_toggle_java
Text for Java button
@snippet samples/java/tutorial_code/introduction/documentation/Documentation.java hello_world
@end_toggle
@add_toggle_python
Text for Python button
@snippet samples/python/tutorial_code/introduction/documentation/documentation.py hello_world
@end_toggle
As you can see, the buttons are added automatically under the previous heading.
### Grouping commands {#tutorial_documentation_commands_group} ### Grouping commands {#tutorial_documentation_commands_group}
All code entities should be put into named groups representing OpenCV modules and their internal All code entities should be put into named groups representing OpenCV modules and their internal
...@@ -536,6 +613,8 @@ Write the tutorial {#tutorial_documentation_steps_tutorial} ...@@ -536,6 +613,8 @@ Write the tutorial {#tutorial_documentation_steps_tutorial}
If you want to insert code blocks from this file into your tutorial, mark them with special doxygen comments (see [here](@ref tutorial_documentation_commands_include)). If you want to insert code blocks from this file into your tutorial, mark them with special doxygen comments (see [here](@ref tutorial_documentation_commands_include)).
If you want to write the tutorial in more than one programming language, use the toggle buttons for alternative comments and code (see [here](@ref tutorial_documentation_toggle_buttons_commands_include)).
3. Collect results of the application work. It can be "before/after" images or some numbers 3. Collect results of the application work. It can be "before/after" images or some numbers
representing performance or even a video. representing performance or even a video.
...@@ -552,22 +631,21 @@ Write the tutorial {#tutorial_documentation_steps_tutorial} ...@@ -552,22 +631,21 @@ Write the tutorial {#tutorial_documentation_steps_tutorial}
5. Modify your new page: 5. Modify your new page:
- Add page title and identifier, usually prefixed with <em>"tutorial_"</em> (see [here](@ref tutorial_documentation_md_page)). - Add page title and identifier, usually prefixed with <em>"tutorial_"</em> (see [here](@ref tutorial_documentation_md_page)).
You can add a link to the previous and next tutorial using the identifier
@verbatim
@prev_tutorial{identifier}
@next_tutorial{identifier}
@endverbatim
@warning Do **not** write the **hashtag (#)**, example: \n Incorrect: @verbatim @prev_tutorial{#tutorial_documentation} @endverbatim Correct: @verbatim @prev_tutorial{tutorial_documentation} @endverbatim
- Add brief description of your idea and tutorial goals. - Add brief description of your idea and tutorial goals.
- Describe your program and/or its interesting pieces. - Describe your program and/or its interesting pieces.
- Describe your results, insert previously added images or other results. - Describe your results, insert previously added images or other results.
To add a video use _htmlonly_, _endhtmlonly_ commands with raw html block inside: To add a youtube video, e.g. www.youtube.com/watch?v= **ViPN810E0SU**, use _youtube_{**Video ID**}:
@verbatim @verbatim
@htmlonly @youtube{ViPN810E0SU}
<div align="center">
<iframe
title="my title" width="560" height="349"
src="http://www.youtube.com/embed/ViPN810E0SU?rel=0&loop=1"
frameborder="0" allowfullscreen align="middle">
</iframe>
</div>
@endhtmlonly
@endverbatim @endverbatim
- Add bibliographic references if any (see [here](@ref tutorial_documentation_commands_cite)). - Add bibliographic references if any (see [here](@ref tutorial_documentation_commands_cite)).
6. Add newly created tutorial to the corresponding table of contents. Just find 6. Add newly created tutorial to the corresponding table of contents. Just find
...@@ -576,6 +654,8 @@ Write the tutorial {#tutorial_documentation_steps_tutorial} ...@@ -576,6 +654,8 @@ Write the tutorial {#tutorial_documentation_steps_tutorial}
@verbatim @verbatim
- @subpage tutorial_windows_visual_studio_image_watch - @subpage tutorial_windows_visual_studio_image_watch
_Languages:_ C++, Java, Python
_Compatibility:_ \>= OpenCV 2.4 _Compatibility:_ \>= OpenCV 2.4
_Author:_ Wolf Kienzle _Author:_ Wolf Kienzle
......
...@@ -50,11 +50,17 @@ int main( int argc, char* argv[]) ...@@ -50,11 +50,17 @@ int main( int argc, char* argv[])
imshow( "Output", dst0 ); imshow( "Output", dst0 );
waitKey(); waitKey();
//![kern]
Mat kernel = (Mat_<char>(3,3) << 0, -1, 0, Mat kernel = (Mat_<char>(3,3) << 0, -1, 0,
-1, 5, -1, -1, 5, -1,
0, -1, 0); 0, -1, 0);
//![kern]
t = (double)getTickCount(); t = (double)getTickCount();
//![filter2D]
filter2D( src, dst1, src.depth(), kernel ); filter2D( src, dst1, src.depth(), kernel );
//![filter2D]
t = ((double)getTickCount() - t)/getTickFrequency(); t = ((double)getTickCount() - t)/getTickFrequency();
cout << "Built-in filter2D time passed in seconds: " << t << endl; cout << "Built-in filter2D time passed in seconds: " << t << endl;
...@@ -63,13 +69,19 @@ int main( int argc, char* argv[]) ...@@ -63,13 +69,19 @@ int main( int argc, char* argv[])
waitKey(); waitKey();
return 0; return 0;
} }
//! [basic_method]
void Sharpen(const Mat& myImage,Mat& Result) void Sharpen(const Mat& myImage,Mat& Result)
{ {
//! [8_bit]
CV_Assert(myImage.depth() == CV_8U); // accept only uchar images CV_Assert(myImage.depth() == CV_8U); // accept only uchar images
//! [8_bit]
//! [create_channels]
const int nChannels = myImage.channels(); const int nChannels = myImage.channels();
Result.create(myImage.size(),myImage.type()); Result.create(myImage.size(),myImage.type());
//! [create_channels]
//! [basic_method_loop]
for(int j = 1 ; j < myImage.rows-1; ++j) for(int j = 1 ; j < myImage.rows-1; ++j)
{ {
const uchar* previous = myImage.ptr<uchar>(j - 1); const uchar* previous = myImage.ptr<uchar>(j - 1);
...@@ -84,9 +96,13 @@ void Sharpen(const Mat& myImage,Mat& Result) ...@@ -84,9 +96,13 @@ void Sharpen(const Mat& myImage,Mat& Result)
-current[i-nChannels] - current[i+nChannels] - previous[i] - next[i]); -current[i-nChannels] - current[i+nChannels] - previous[i] - next[i]);
} }
} }
//! [basic_method_loop]
//! [borders]
Result.row(0).setTo(Scalar(0)); Result.row(0).setTo(Scalar(0));
Result.row(Result.rows-1).setTo(Scalar(0)); Result.row(Result.rows-1).setTo(Scalar(0));
Result.col(0).setTo(Scalar(0)); Result.col(0).setTo(Scalar(0));
Result.col(Result.cols-1).setTo(Scalar(0)); Result.col(Result.cols-1).setTo(Scalar(0));
//! [borders]
} }
//! [basic_method]
#include <iostream>
/**
* @function main
* @brief Main function
*/
int main( void )
{
//! [hello_world]
std::cout << "Hello World!";
//! [hello_world]
return 0;
}
import org.opencv.core.*;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
import javax.swing.*;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte;
class MatMaskOperationsRun {
public void run() {
//! [laod_image]
Mat I = Imgcodecs.imread("../data/lena.jpg");
if(I.empty())
System.out.println("Error opening image");
//! [laod_image]
Image img = toBufferedImage( I );
displayImage("Input Image" , img, 0, 200 );
double t = System.currentTimeMillis();
Mat J = sharpen(I, new Mat());
t = ((double)System.currentTimeMillis() - t)/1000;
System.out.println("Hand written function times passed in seconds: " + t);
Image img2 = toBufferedImage( J );
displayImage("Output Image" , img2, 400, 400 );
Mat K = new Mat();
//![kern]
Mat kern = new Mat( 3, 3, CvType.CV_8S );
int row = 0, col = 0;
kern.put(row ,col, 0, -1, 0, -1, 5, -1, 0, -1, 0 );
//![kern]
System.out.println("kern = \n" + kern.dump());
t = System.currentTimeMillis();
//![filter2D]
Imgproc.filter2D(I, K, I.depth(), kern );
//![filter2D]
t = ((double)System.currentTimeMillis() - t)/1000;
System.out.println("Built-in filter2D time passed in seconds: " + t);
Image img3 = toBufferedImage( J );
displayImage("filter2D Output Image" , img3, 800, 400 );
}
//! [basic_method]
public static double saturateCastUchar(double x) {
return x > 255.0 ? 255.0 : (x < 0.0 ? 0.0 : x);
}
public Mat sharpen(Mat myImage, Mat Result)
{
//! [8_bit]
myImage.convertTo(myImage, CvType.CV_8U);
//! [8_bit]
//! [create_channels]
int nChannels = myImage.channels();
Result.create(myImage.size(),myImage.type());
//! [create_channels]
//! [basic_method_loop]
for(int j = 1 ; j < myImage.rows()-1; ++j)
{
for(int i = 1 ; i < myImage.cols()-1; ++i)
{
double sum[] = new double[nChannels];
for(int k = 0; k < nChannels; ++k) {
double top = -myImage.get(j - 1, i)[k];
double bottom = -myImage.get(j + 1, i)[k];
double center = (5 * myImage.get(j, i)[k]);
double left = -myImage.get(j , i - 1)[k];
double right = -myImage.get(j , i + 1)[k];
sum[k] = saturateCastUchar(top + bottom + center + left + right);
}
Result.put(j, i, sum);
}
}
//! [basic_method_loop]
//! [borders]
Result.row(0).setTo(new Scalar(0));
Result.row(Result.rows()-1).setTo(new Scalar(0));
Result.col(0).setTo(new Scalar(0));
Result.col(Result.cols()-1).setTo(new Scalar(0));
//! [borders]
return Result;
}
//! [basic_method]
public Image toBufferedImage(Mat m) {
int type = BufferedImage.TYPE_BYTE_GRAY;
if ( m.channels() > 1 ) {
type = BufferedImage.TYPE_3BYTE_BGR;
}
int bufferSize = m.channels()*m.cols()*m.rows();
byte [] b = new byte[bufferSize];
m.get(0,0,b); // get all the pixels
BufferedImage image = new BufferedImage(m.cols(),m.rows(), type);
final byte[] targetPixels = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
System.arraycopy(b, 0, targetPixels, 0, b.length);
return image;
}
public void displayImage(String title, Image img, int x, int y)
{
ImageIcon icon=new ImageIcon(img);
JFrame frame=new JFrame(title);
JLabel lbl=new JLabel(icon);
frame.add(lbl);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocation(x, y);
frame.setVisible(true);
}
}
public class MatMaskOperations {
public static void main(String[] args) {
// Load the native library.
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
new MatMaskOperationsRun().run();
}
}
public class Documentation {
public static void main (String[] args) {
//! [hello_world]
System.out.println ("Hello World!");
//! [hello_world]
}
}
import time
import numpy as np
import cv2
## [basic_method]
def sharpen(my_image):
my_image = cv2.cvtColor(my_image, cv2.CV_8U)
height, width, n_channels = my_image.shape
result = np.zeros(my_image.shape, my_image.dtype)
## [basic_method_loop]
for j in range (1, height-1):
for i in range (1, width-1):
for k in range (0, n_channels):
sum = 5 * my_image[j, i, k] - my_image[j + 1, i, k] - my_image[j - 1, i, k]\
- my_image[j, i + 1, k] - my_image[j, i - 1, k];
if sum > 255:
sum = 255
if sum < 0:
sum = 0
result[j, i, k] = sum
## [basic_method_loop]
return result
## [basic_method]
I = cv2.imread("../data/lena.jpg")
cv2.imshow('Input Image', I)
t = round(time.time())
J = sharpen(I)
t = (time.time() - t)/1000
print "Hand written function times passed in seconds: %s" % t
cv2.imshow('Output Image', J)
t = time.time()
## [kern]
kernel = np.array([ [0,-1,0],
[-1,5,-1],
[0,-1,0] ],np.float32) # kernel should be floating point type
## [kern]
## [filter2D]
K = cv2.filter2D(I, -1, kernel) # ddepth = -1, means destination image has depth same as input image.
## [filter2D]
t = (time.time() - t)/1000
print "Built-in filter2D time passed in seconds: %s" % t
cv2.imshow('filter2D Output Image', K)
cv2.waitKey(0)
cv2.destroyAllWindows()
print('Not showing this text because it is outside the snippet')
## [hello_world]
print('Hello world!')
## [hello_world]
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment