Something More for Research

Explorer of Research #HEMBAD

Databases for Multi-camera , Network Camera , E-Surveillace

Posted by Hemprasad Y. Badgujar on February 18, 2016


Multi-view, Multi-Class Dataset: pedestrians, cars and buses

This dataset consists of 23 minutes and 57 seconds of synchronized frames taken at 25fps from 6 different calibrated DV cameras.
One camera was placed about 2m high of the ground, two others where located on a first floor high, and the rest on a second floor to cover an area of 22m x 22m.
The sequence was recorded at the EPFL university campus where there is a road with a bus stop, parking slots for cars and a pedestrian crossing.

Download

Ground truth images
Ground truth annotations

References

The dataset on this page has been used for our multiview object pose estimation algorithm described in the following paper:

G. Roig, X. Boix, H. Ben Shitrit and P. Fua Conditional Random Fields for Multi-Camera Object Detection, ICCV11.

Multi-camera pedestrians video

“EPFL” data set: Multi-camera Pedestrian Videos

people tracking
results, please cite one of the references below.

On this page you can download a few multi-camera sequences that we acquired for developing and testing our people detection and tracking framework. All of the sequences feature several synchronised video streams filming the same area under different angles. All cameras are located about 2 meters from the ground. All pedestrians on the sequences are members of our laboratory, so there is no privacy issue. For the Basketball sequence, we received consent from the team.

Laboratory sequences

These sequences were shot inside our laboratory by 4 cameras. Four (respectively six) people are sequentially entering the room and walking around for 2 1/2 minutes. The frame rate is 25 fps and the videos are encoded using MPEG-4 codec.

[Camera 0] [Camera 1] [Camera 2] [Camera 3]

Calibration file for the 4 people indoor sequence.

[Camera 0] [Camera 1] [Camera 2] [Camera 3]

Calibration file for the 6 people indoor sequence.

Campus sequences

These two sequences called campus were shot outside on our campus with 3 DV cameras. Up to four people are simultaneously walking in front of them. The white line on the screenshots shows the limits of the area that we defined to obtain our tracking results. The frame rate is 25 fps and the videos are encoded using Indeo 5 codec.

[Seq.1, cam. 0] [Seq.1, cam. 1] [Seq.1, cam. 2]
[Seq.2, cam. 0] [Seq.2, cam. 1] [Seq.2, cam. 2]

Calibration file for the two above outdoor scenes.

Terrace sequences

The sequences below, called terrace, were shot outside our building on a terrace. Up to 7 people evolve in front of 4 DV cameras, for around 3 1/2 minutes. The frame rate is 25 fps and the videos are encoded using Indeo 5 codec.

[Seq.1, cam. 0] [Seq.1, cam. 1] [Seq.1, cam. 2] [Seq.1, cam. 3]
[Seq.2, cam. 0] [Seq.2, cam. 1] [Seq.2, cam. 2] [Seq.1, cam. 3]

Calibration file for the terrace scene.

Passageway sequence

This sequence dubbed passageway was filmed in an underground passageway to a train station. It was acquired with 4 DV cameras at 25 fps, and is encoded with Indeo 5. It is a rather difficult sequence due to the poor lighting.

[Seq.1, cam. 0] [Seq.1, cam. 1] [Seq.1, cam. 2] [Seq.1, cam. 3]

Calibration file for the passageway scene.

Basketball sequence

This sequence was filmed at a training session of a local basketball team. It was acquired with 4 DV cameras at 25 fps, and is encoded with Indeo 5.

[Seq.1, cam. 0] [Seq.1, cam. 1] [Seq.1, cam. 2] [Seq.1, cam. 3]

Calibration file for the basketball scene.

Camera calibration

POM only needs a simple calibration consisting of two homographies per camera view, which project the ground plane in top view to the ground plane in camera views and to the head plane in camera views (a plane parallel to the ground plane but located 1.75 m higher). Therefore, the calibration files given above consist of 2 homographies per camera. In degenerate cases where the camera is located inside the head plane, this one will project to a horizontal line in the camera image. When this happens, we do not provide a homography for the head plane, but instead we give the height of the line in which the head plane will project. This is expressed in percentage of the image height, starting from the top.

The homographies given in the calibration files project points in the camera views to their corresponding location on the top view of the ground plane, that is

H * X_image = X_topview .

We have also computed the camera calibration using the Tsai calibration toolkit for some of our sequences. We also make them available for download. They consist of an XML file per camera view, containing the standard Tsai calibration parameters. Note that the image size used for calibration might differ from the size of the video sequences. In this case, the image coordinates obtained with the calibration should be normalized to the size of the video.

Ground truth

We have created a ground truth data for some of the video sequences presented above, by locating and identifying the people in some frames at a regular interval.

To use these ground truth files, you must rely on the same calibration with the exact same parameters that we used when generating the data. We call top view the rectangular area of the ground plane in which we perform tracking.

This area is of dimensions tv_width x tv_height and has top left coordinate (tv_origin_x, tv_origin_y). Besides, we call grid our discretization of the top view area into grid_width x grid_height cells. An example is illustrated by the figure below, in which the grid has dimensions 5 x 4.

The people’s position in the ground truth are expressed in discrete grid coordinates. In order to be projected into the images with homographies or the Tsai calibration, these grid coordinates need to be translated into top view coordinates. We provide below a simple C function that performs this translation. This function takes the following parameters:

  • pos : the person position coming from the ground truth file
  • grid_width, grid_height : the grid dimension
  • tv_origin_x, tv_origin_y : the top left corner of the top view
  • tv_width, tv_height : the top view dimension
  • tv_x, tv_y : the top view coordinates, i.e. the output of the function
  void grid_to_tv(int pos, int grid_width, int grid_height,                  float tv_origin_x, float tv_origin_y, float tv_width,                  float tv_height, float &tv_x, float &tv_y) {     tv_x = ( (pos % grid_width) + 0.5 ) * (tv_width / grid_width) + tv_origin_x;    tv_y = ( (pos / grid_width) + 0.5 ) * (tv_height / grid_height) + tv_origin_y;  }

The table below summarizes the aforementionned parameters for the ground truth files we provide. Note that the ground truth for the terrace sequence has been generated with the Tsai calibration provided in the table. You will need to use this one to get a proper bounding box alignment.

Ground Truth Grid dimensions Top view origin Top view dimensions Calibration
6-people laboratory 56 x 56 (0 , 0) 358 x 360 file
terrace, seq. 1 30 x 44 (-500 , -1,500) 7,500 x 11,000 file (Tsai)
passageway, seq. 1 40 x 99 (0 , 38.48) 155 x 381 file

The format of the ground truth file is the following:

 1 <number of frames>  <number of people>  <grid width>  <grid height>  <step size>  <first frame>  <last frame> <pos> <pos> <pos> ... <pos> <pos> <pos> ... . . .

where <number of frames> is the total number of frames, <number of people> is the number of people for which we have produced a ground truth, <grid width> and <grid height>are the ground plane grid dimensions, <step size> is the frame interval between two ground truth labels (i.e. if set to 25, then there is a label once every 25 frames), and <first frame> and <last frame> are the first and last frames for which a label has been entered.

After the header, every line represents the positions of people at a given frame. <pos> is the position of a person in the grid. It is normally a integer >= 0, but can be -1 if undefined (i.e. no label has been produced for this frame) or -2 if the person is currently out of the grid.

References

Multiple Object Tracking using K-Shortest Paths Optimization

Jérôme Berclaz, François Fleuret, Engin Türetken, Pascal Fua
IEEE Transactions on Pattern Analysis and Machine Intelligence
2011
pdf | show bibtex

Multi-Camera People Tracking with a Probabilistic Occupancy Map

François Fleuret, Jérôme Berclaz, Richard Lengagne, Pascal Fua
IEEE Transactions on Pattern Analysis and Machine Intelligence
pdf | show bibtex

MuHAVi: Multicamera Human Action Video Data

including selected action sequences with

MAS: Manually Annotated Silhouette Data

for the evaluation of human action recognition methods

Figure 1. The top view of the configuration of 8 cameras used to capture the actions in the blue action zone (which is marked with white tapes on the scene floor).

camera symbol

camera name

V1 Camera_1
V2 Camera_2
V3 Camera_3
V4 Camera_4
V5 Camera_5
V6 Camera_6
V7 Camera_7
V8 Camera_8

Table 1. Camera view names appearing in the MuHAVi data folders and the corresponding symbols used in Fig. 1.

 

On the table below, you can click on the links to download the data (JPG images) for the corresponding action

Important: We noted that some earlier versions of that earlier versions of MS Internet Explorer could not download files over 2GB size, so we recomment to use alternative browsers such as Firefox or Chrome.

Each tar file contains 7 folders corresponding to 7 actors (Person1 to Person7) each of which contains 8 folders corresponding to 8 cameras (Camera_1 to Camera_8). Image frames corresponding to every combination of action/actor/camera are named with image frame numbers starting from 00000001.jpg for simplicity. The video frame rate is 25 frames per second and the resolution of image frames (except for Camera_8) is 720 x 576 Pixels (columns x rows). The image resolution is 704 x 576 for Camera_8.

action class

action name

size
C1 WalkTurnBack 2.6GB
C2 RunStop 2.5GB
C3 Punch 3.0GB
C4 Kick 3.4GB
C5 ShotGunCollapse 4.3GB
C6 PullHeavyObject 4.5GB
C7 PickupThrowObject 3.0GB
C8 WalkFall 3.9GB
C9 LookInCar 4.6GB
C10 CrawlOnKnees 3.4GB
C11 WaveArms 2.2GB
C12 DrawGraffiti 2.7GB
C13 JumpOverFence 4.4GB
C14 DrunkWalk 4.0GB
C15 ClimbLadder 2.1GB
C16 SmashObject 3.3GB
C17 JumpOverGap 2.6GB

MIT Trajectory Data Set – Multiple Camera Views

Download

MIT trajectory data set is for the research of activity analysis in multiple single camera view using the trajectories of objects as features. Object tracking is based on background subtraction using a Adaptive Gaussian Mixture model. There are totally four camera views. Trajectories in different camera views have been synchronized. The data can be downloaded from the following link,

MIT trajectory data set

Background image

Reference

Please cite as:

X. Wang, K. Tieu and E. Grimson, Correspondence‐Free Activity Analysis and Scene Modeling in Multiple Camera Views, IEEE Transactions on Pattern Analysis and Machine Intelligence(PAMI), Vol. 32, pp. 56-71, 2010..

Details

MIT traffic data set is for research on activity analysis and crowded scenes. It includes a traffic video sequence of 90 minutes long. It is recorded by a stationary camera. The size of the scene is 720 by 480. It is divided into 20 clips and can be downloaded from the following links.

Ground Truth

In order to evaluate the performance of human detection on this data set, ground truth of pedestrians of some sampled frames are manually labeled. It can be downloaded below. A readme file provides the instructions of how to use it.
Ground truth of pedestrians

References

  1. Unsupervised Activity Perception in Crowded and Complicated scenes Using Hierarchical Bayesian Models
    X. Wang, X. Ma and E. Grimson
    IEEE Transactions on Pattern Analysis and Machine Intelligence (PAMI), Vol. 31, pp. 539-555, 2009
  2. Automatic Adaptation of a Generic Pedestrian Detector to a Specific Traffic Scene
    M. Wang and X. Wang
    IEEE Computer Society Conference on Computer Vision and Pattern Recognition (CVPR), 2011

Description

This dataset is presented in our CVPR 2015 paper,
Linjie Yang, Ping Luo, Chen Change Loy, Xiaoou Tang. A Large-Scale Car Dataset for Fine-Grained Categorization and Verification, In Computer Vision and Pattern Recognition (CVPR), 2015. PDF

The Comprehensive Cars (CompCars) dataset contains data from two scenarios, including images from web-nature and surveillance-nature. The web-nature data contains 163 car makes with 1,716 car models. There are a total of 136,726 images capturing the entire cars and 27,618 images capturing the car parts. The full car images are labeled with bounding boxes and viewpoints. Each car model is labeled with five attributes, including maximum speed, displacement, number of doors, number of seats, and type of car. The surveillance-nature data contains 50,000 car images captured in the front view. Please refer to our paper for the details.

The dataset is well prepared for the following computer vision tasks:

  • Fine-grained classification
  • Attribute prediction
  • Car model verification

The train/test subsets of these tasks introduced in our paper are included in the dataset. Researchers are also welcome to utilize it for any other tasks such as image ranking, multi-task learning, and 3D reconstruction.

Note

  1. You need to complete the release agreement form to download the dataset. Please see below.
  2. The CompCars database is available for non-commercial research purposes only.
  3. All images of the CompCars database are obtained from the Internet which are not property of MMLAB, The Chinese University of Hong Kong. The MMLAB is not responsible for the content nor the meaning of these images.
  4. You agree not to reproduce, duplicate, copy, sell, trade, resell or exploit for any commercial purposes, any portion of the images and any portion of derived data.
  5. You agree not to further copy, publish or distribute any portion of the CompCars database. Except, for internal use at a single site within the same organization it is allowed to make copies of the database.
  6. The MMLAB reserves the right to terminate your access to the database at any time.
  7. All submitted papers or any publicly available text using the CompCars database must cite the following paper:
    Linjie Yang, Ping Luo, Chen Change Loy, Xiaoou Tang. A Large-Scale Car Dataset for Fine-Grained Categorization and Verification, In Computer Vision and Pattern Recognition (CVPR), 2015.

Download instructions

Download the CompCars dataset Release Agreement, read it carefully, and complete it appropriately. Note that the agreement should be signed by a full-time staff member (that is, student is not acceptable). Then, please scan the signed agreement and send it to Mr. Linjie Yang (yl012(at)ie.cuhk.edu.hk) and cc to Chen Change Loy (ccloy(at)ie.cuhk.edu.hk). We will verify your request and contact you on how to download the database.

Stanford Cars Dataset

Overview

       The Cars dataset contains 16,185 images of 196 classes of cars. The data is split into 8,144 training images and 8,041 testing images, where each class has been split roughly in a 50-50 split. Classes are typically at the level of Make, Model, Year, e.g. 2012 Tesla Model S or 2012 BMW M3 coupe.

Download

       Training images can be downloaded here.
Testing images can be downloaded here.
A devkit, including class labels for training images and bounding boxes for all images, can be downloaded here.
If you’re interested in the BMW-10 dataset, you can get that here.

Update: For ease of development, a tar of all images is available here and all bounding boxes and labels for both training and test are available here. If you were using the evaluation server before (which is still running), you can use test annotations here to evaluate yourself without using the server.

Evaluation

       An evaluation server has been set up here. Instructions for the submission format are included in the devkit. This dataset was featured as part of FGComp 2013, and competition results are directly comparable to results obtained from evaluating on images here.

Citation

       If you use this dataset, please cite the following paper:

3D Object Representations for Fine-Grained Categorization
Jonathan Krause, Michael Stark, Jia Deng, Li Fei-Fei
4th IEEE Workshop on 3D Representation and Recognition, at ICCV 2013 (3dRR-13). Sydney, Australia. Dec. 8, 2013.
[pdf]   [BibTex]   [slides]

Note that the dataset, as released, has 196 categories, one less than in the paper, as it has been cleaned up slightly since publication. Numbers should be more or less comparable, though.

The HDA dataset is a multi-camera high-resolution image sequence dataset for research on high-definition surveillance. 18 cameras (including VGA, HD and Full HD resolution) were recorded simultaneously during 30 minutes in a typical indoor office scenario at a busy hour (lunch time) involving more than 80 persons. In the current release (v1.1), 13 cameras have been fully labeled.

 

The venue spans three floors of the Institute for Systems and Robotics (ISR-Lisbon) facilities. The following pictures show the placement of the cameras. The 18 recorded cameras are identified with a small red circle. The 13 cameras with a coloured view field have been fully labeled in the current release (v1.1).

 

Each frame is labeled with the bounding boxes tightly adjusted to the visible body of the persons, the unique identification of each person, and flag bits indicating occlusion and crowd:

  • The bounding box is drawn so that it completely and tightly encloses the person.
  • If the person is occluded by something (except image boundaries), the bounding box is drawn by estimating the whole body extent.
  • People partially outside the image boundaries have their BB’s cropped to image limits. Partially occluded people and people partially outside the image boundaries are marked as ‘occluded’.
  • A unique ID is associated to each person, e.g., ‘person01’. In case of identity doubt, the special ID ‘personUnk’ is used.
  • Groups of people that are impossible to label individually are labelled collectively as ‘crowd’. People in front of a ’crowd’ area are labeled normally.

The following figures show examples of labeled frames: (a) an unoccluded person; (b) two occluded people; (c) a crowd with three people in front.

 

Data formats:

For each camera we provide the .jpg frames sequentially numbered and a .txt file containing the annotations according to the “video bounding box” (vbb) format defined in the Caltech Pedestrian Detection Database. Also on this site there are tools to visualise the annotations overlapped on the image frames.

 

Some statistics:

Labeled Sequences: 13

Number of Frames: 75207

Number of Bounding Boxes: 64028

Number of Persons: 85

 

Repository of Results:

We maintain a public repository of re-identification results in this dataset. Send us your CMC curve to be uploaded  (alex at isr ist utl pt).
Click here to see the full list and detailed experiments.

MANUAL_c_l_e_a_n cam60

Posted in Computer Network & Security, Computer Research, Computer Vision, Image Processing, Multimedia | Leave a Comment »

How to use Twitter as a scientist

Posted by Hemprasad Y. Badgujar on February 5, 2016


fwis-loreal-10-women-scientists-you-should-follow-on-twitter-264.jpg

if you are a scientist, with “joining Twitter” and then “doing stuff with Twitter” on your To Do list, you might feel a little intimidated by the long list of possible people to follow. Moreover, following @CNN and @BarackObama might be the first thing you do, and might be suggested to you, but these are not your main sources of scientific joy and information.

So let’s take this step by step. Let’s go from setting up a profile, following people to building an academic network on Twitter. I don’t want this to become like a tutorial (there’s plenty of videos on YouTube to take you through any step you might have difficulties with), but I want to give you some tips and tricks at every step along the process.

1. Crafting a bio
One of the first things you need to do when you sign up on Twitter, is to put a bio. I recommend that you make your Twitter profile publicly accessible instead of private. If you join Twitter to enter the realm of scientists on Twitter, you’d prefer them to be able to find you and follow you. Make sure your bio mentions your field and institution(s). You can add a warning that Retweets are not Endorsements, but, really, most of the Twitterverse is aware of that.

Keep in mind as well that Twitter is a lighter type of platform. There’s no need for you to cite your recent publications in your bio. I like to add a bit of lightness to my bio by adding “Blogs. Pets cats. Drinks tea.” I’m assuming that also sets up people for the fact that besides the concrete and the science, I could blurt out the odd complaint, random observation or retweet cute cat pictures if I feel like. Does that make me unprofessional? I’m on the border of Gen Y and I don’t think so…

2. Choosing a profile picture
Your standard profile picture is an egg. Whenever I get followed by an egg, I don’t even take the effort to read the profile description of this person, because the sole fact that he/she didn’t even finish his/her profile, makes me doubt this person has any real interest in interacting on Twitter.

Since Twitter profile pictures show up very small, I recommend you use a headshot. If you put a full body picture of yourself presenting your work somewhere, you’ll be reduced to the size of a stickman in people’s timelines. Use a clear, recognizable headshot, so that the odd fellow researcher might be able to recognize you at a conference.

3. Following people

So now that we have the basics covered, let’s start to move forward into the actual use of Twitter. Your first recommended people to follow will typically be @CNN and @BarackObama. While I like using Twitter as a source for the news, I’m going to assume you came here in the first place for the scientific community. How do you start following people?

Here are a few types of accounts that you can/should start following:
– the accounts of your university and department. These accounts will also retweet tweets from fellow academics at your institute.
– the accounts of universities and research groups worldwide you are interested in.
– the accounts of academic publishers
– the accounts of news websites and blogs related with higher education, such as @insidehighered
– make a search for your field and see what and who shows up
– organizations in your field
– Twitter lists about your field or with people from your institution

Keep in mind that, just like growing followers, growing a list of interesting people to follow is something that happens over time. You might see a retweet of somebody, check out his/her profile and then decide to follow this tweep. If you start aggressively following a lot of people in a short amount of time, Twitter will ban you from following more people anyway.

4. Creating content
Now you can start creating content. You can tweet about your recent publications, retweet information from the accounts you follow and more. If you have a blog, Twitter is an excellent place to share your recent blog posts. You can also tweet series of posts (indicated by (1/3), (2/3) and (3/3) if you distribute it over 3 posts, for example) of the contents that you want to share is too long to squeeze into 150 characters.

Some ideas on what to share with the world:
– tweet about the topic you will discuss in class
– tweet about the conference you are planning to attend
– share your progress in writing
– talk about a recent publication
– join the discussion about higher education policies (I know you have an opinion – we all do)

5. Getting the discussion started
If you see a topic of your interest, you don’t need to wait for anyone to invite you to take part in the discussion – you can imply barge right into it. You wouldn’t do it in real life, but on Twitter, nobody knows you are reading along. So comment to what fellow researchers are sharing, ask for ideas and opinions and interact.

You can also tag people in a post by adding their @name when you share an article and ask what they think. In this way, you can as well get involved in the academic online discussion.

6. Using hashtags
Hashtags, those #selfie #dinner #random stuff that you see showing up around most social media platforms come from Twitter, where feeds and discussions center around certain hashtags. In the academic world, I recommend you to check out #phdchat, #ecrchat (for early career researchers), #scholarsunday (on Sundays, to learn who to follow), #acwri (for academic writing) and #acwrimo (in November, the month in which academics worldwide pledge to get their manuscript out and post their daily word counts).

Some hashtags have a weekly fixed hour to chat. Other hashtags are continuous streams of information. Figure out what the important hashtags are in your field and in academia in general, listen in and contribute.

7. Saving conversations with Storify

If you had a particularly interesting conversation on Twitter that you would like to save for future reference, you can use Storify. Storify is a website on which you can save stories, by adding social media content. You can, for example, add tweets and replies to tweets in a logical order, to save a discussion you had. Once you finished compiling your story, you can share it again through social media. Stories also remain saved and accessible for the future in Storify.

8. Curating content
Retweeting, sharing articles, hosting people to write on your blog, … all these activities are related to curating content and broadcasting it to your audience. I enjoy interviewing fellow academics that I meet through Twitter. I post the interview then on my blog, and share that link on Twitter (going full circle). From a number of newsletters that I read, I also share articles and interesting documents. Find out what type of content you and your followers find relevant, and start distributing interesting information.

Posted in Computing Technology, Mixed, My Research Related | Tagged: , , , , | Leave a Comment »

HOW TO PASS COMMAND-LINE ARGUMENTS IN ECLIPSE IDE?

Posted by Hemprasad Y. Badgujar on November 30, 2015


New Java Project

  • Create a new Java Project and name it as “CommandLineArguments

Right click on Package Explorer -> New -> Project -> Select Java Project

New package

  • Create a new Package and name it as “commandline

Right click on src -> New -> Package

New Class

  • Create a new Java Class and name it as “AdditionOfTwoNumbers” in the package “commandline“. Make sure you select main method option.

Right click on commandline package -> New -> Class

Paste this code in the main method.

01
02
03
04
05
06
07
08
09
10
11
package commandline;
public class AdditionOfTwoNumbers {
    public static void main(String[] args) {
        int a, b;
        a = Integer.parseInt(args[0]);
        b = Integer.parseInt(args[1]);
        
        int sum = a + b;
        System.out.println("The Sum is: " + sum);
    }
}

Save the program.

  • Press [Ctrl + s] to save your program

Run Configurations

Go to Run menu and select Run Configurations. Run Configurations dialogue box opens.

Run your program

  • Select your Java class from the left side column. If you do not find your class, then click on the “New launch Configuration” button, found above the class list.
  • In the right side menu select “Arguments” tab
  • In the “Program Arguments” text area type the input numbers separated by spaces or newline.
  • Click Run button.

Output

  • You will see the output in the console.

The Sum is: 32

Posted in Mixed | Leave a Comment »

CUDA Unified Memory

Posted by Hemprasad Y. Badgujar on October 6, 2015


CUDA Unified Memory

CUDA is the language of Nvidia GPU’s.  To extract maximum performance from GPU’s, you’ll want to develop applications in CUDA.

CUDA Toolkit is the primary IDE (integrated development environment) for developing CUDA-enabled applications.  The main roles of the Toolkit IDE are to simplify the software development process, maximize software developer productivity, and provide features that enhance GPU performance.  The Toolkit has been steadily evolving in tandem with GPU hardware and currently sits at Version 6.5.

One of the most important features of CUDA 6.5 is Unified Memory (UM).  (UM was actually first introduced in CUDA v.6.0).  CPU host memory and GPU device memory are physically separate entities, connected by a relatively slow PCIe bus.  Prior to v.6.0, data elements shared in both CPU and GPU memory required two copies – one copy in CPU memory and one copy in GPU memory.  Developers had to allocate memory on the CPU, allocate memory on the GPU, and then copy data from CPU to GPU and from GPU to CPU.  This dual data management scheme added complexity to programs, opportunities for the introduction of software bugs, and an excessive focus of time and energy on data management tasks.

UM corrects this.  UM creates a memory pool that is shared between CPU and GPU, with a single memory address space and single pointers accessible to both host and device code.  The CUDA driver and runtime libraries automatically handle data transfers between host and device memory, thus relieving developers from the burden of explicitly managing those data transfers.  UM improves performance by automatically providing data locality on the CPU or GPU, wherever it might be required by the application algorithm.  UM also guarantees global coherency of data on host and device, thus reducing the introduction of software bugs.

Let’s explore some sample code that illustrates these concepts.  We won’t concern ourselves with the function of this algorithm; instead, we’ll just focus on the syntax. (Credit to Nvidia for this C/CUDA template example).

Without Unified Memory

Without Unified Memory

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#include <string.h>
#include <stdio.h>
struct DataElement
{
  char *name;
  int value;
};
__global__
void Kernel(DataElement *elem) {
  printf("On device: name=%s, value=%d\n", elem->name, elem->value;
  elem->name[0] = 'd';
  elem->value++;
}
void launch(DataElement *elem) {
  DataElement *d_elem;
  char *d_name;
  int namelen = strlen(elem->name) + 1;
  // Allocate memory on GPU
  cudaMalloc(&d_elem, sizeofDataElement());
  cudaMalloc(&d_name, namelen);
  // Copy data from CPU to GPU
  cudaMemcpy(d_elem, elem, sizeof(DataElement),
     cudaMemcpyHostToDevice);
  cudaMemcpy(d_name, elem->name, namelen, cudaMemcpyHostToDevice);
  cudaMemcpy(&(d_elem->name), &d_name, sizeof(char*),
     cudaMemcpyHostToDevice);
  // Launch kernel
  Kernel<<< 1, 1 >>>(d_elem);
  // Copy data from GPU to CPU
  cudaMemcpy(&(elem->value), &(d_elem->value), sizeof(int),
     cudaMemcpyDeviceToHost);
  cudaMemcpy(elem->name, d_name, namelen, cudaMemcpyDeviceToHost);
  cudaFree(d_name);
  cudaFree(d_elem);
}
int main(void)
{
  DataElement *e;
  // Allocate memory on CPU
  e = (DataElement*)malloc(sizeof(DataElement));
  e->value = 10;
  // Allocate memory on CPU
  e->name = (char*)malloc(sizeof(char) * (strlen("hello") + 1));
  strcpy(e->name, "hello");
  launch(e);
  printf("On host: name=%s, value=%d\n", e->name, e->value);
  free(e->name);
  free(e);
  cudaDeviceReset();
}

Note these key points:

  • L51,55: Allocate memory on CPU
  • L24,25: Allocate memory on GPU
  • L28-32: Copy data from CPU to GPU
  • L35: Run kernel
  • L38-40: Copy data from GPU to CPU

With Unified Memory 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include <string.h>
#include <stdio.h>
struct DataElement
{
  char *name;
  int value;
};
__global__
void Kernel(DataElement *elem) {
  printf("On device: name=%s, value=%d\n", elem->name, elem->value;
  elem->name[0] = 'd';
  elem->value++;
}
void launch(DataElement *elem) {
  // Launch kernel
  Kernel<<< 1, 1 >>>(elem);
  cudaDeviceSynchronize();
}
int main(void)
{
  DataElement *e;
  // Allocate unified memory on CPU and GPU
  cudaMallocManaged((void**)&e, sizeof(DataElement));
  e->value = 10;
  // Allocate unified memory on CPU and GPU
  cudaMallocManaged((void**)&(e->name), sizeof(char) *
     (strlen("hello") + 1) );
  strcpy(e->name, "hello");
  launch(e);
  printf("On host: name=%s, value=%d\n", e->name, e->value);
  cudaFree(e->name);
  cudaFree(e);
  cudaDeviceReset();
}
 

Note these key points:

  • L28, 32, 33: Allocate unified memory on CPU and GPU
  • L19: Run kernel

With UM, memory is allocated on the CPU and GPU in a single address space and managed with a single pointer.  Note how the “malloc’s” and “cudaMalloc’s” are condensed into single calls to cudaMallocManaged().  Furthermore, explicit cudaMemcpy() data transfers between CPU and GPU are eliminated, as the CUDA runtime handles these transfers automatically in the background. Collectively these actions simplify code development, code maintenance, and data management.

As software project managers, we like UM for the productivity enhancements it provides for our software development teams.  It improves software quality, reduces coding time, effort and cost, and enhances overall performance. As software engineers, we like UM because of reduced coding effort and the fact that we can focus time and effort on writing CUDA kernel code, where all the parallel performance comes from, instead of spending time on memory management tasks.  Unified Memory is major step forward in GPU programming.

Posted in CUDA, CUDA TUTORIALS, GPU (CUDA), PARALLEL | Leave a Comment »

CUDA Random Numbers

Posted by Hemprasad Y. Badgujar on October 3, 2015


CUDA Random Example

In order to use cuRAND, we need to add two include files into our program:

#include &lt;curand.h&gt;
#include &lt;curand_kernel.h&gt;

cuRAND uses a curandState_t type to keep track of the state of the random sequence. The normal C rand function also has a state, but it is global, and hidden from the programmer. This makes rand not thread-safe, but easier to use.

A curandState_t object must be initialized with a call to curand_init which has the following parameters:

  • seed: The seed determines the beginning point of the sequence of random numbers.
  • sequence: The sequence number is another seed-like value. It is used so that, if all cores have the same seed, but different sequence numbers, then they will get different random values.
  • offset: The amount we skip ahead in the random sequence. This can be zero.
  • state: A pointer to the curandState_t object to initialize.

Once we have an initialized curandState_t object, we can get random numbers with the curand function which takes a pointer to a curandState_t object and returns to us a random unsigned integer.

The following program uses these functions to generate random numbers:

#include <unistd.h>
#include <stdio.h>

/* we need these includes for CUDA's random number stuff */
#include <curand.h>
#include 

#define MAX 100

/* this GPU kernel function calculates a random number and stores it in the parameter */
__global__ void random(int* result) {
  /* CUDA's random number library uses curandState_t to keep track of the seed value
     we will store a random state for every thread  */
  curandState_t state;

  /* we have to initialize the state */
  curand_init(0, /* the seed controls the sequence of random values that are produced */
              0, /* the sequence number is only important with multiple cores */
              0, /* the offset is how much extra we advance in the sequence for each call, can be 0 */
              &state);

  /* curand works like rand - except that it takes a state as a parameter */
  *result = curand(&state) % MAX;
}

int main( ) {
  /* allocate an int on the GPU */
  int* gpu_x;
  cudaMalloc((void**) &gpu_x, sizeof(int));

  /* invoke the GPU to initialize all of the random states */
  random<<<1, 1>>>(gpu_x);

  /* copy the random number back */
  int x;
  cudaMemcpy(&x, gpu_x, sizeof(int), cudaMemcpyDeviceToHost);

  printf("Random number = %d.\n", x);

  /* free the memory we allocated */
  cudaFree(gpu_x);

  return 0;
}

When run, this program produces the exact same random number each time. This is because the seed passed in was 0. In order to get a different random number each time, we can pass in the current time as the seed.


#include <unistd.h>
#include <stdio.h>

/* we need these includes for CUDA's random number stuff */

#include 
#include 

#define MAX 100

/* this GPU kernel function calculates a random number and stores it in the parameter */
__global__ void random(unsigned int seed, int* result) {
  /* CUDA's random number library uses curandState_t to keep track of the seed value
     we will store a random state for every thread  */
  curandState_t state;

  /* we have to initialize the state */
  curand_init(seed, /* the seed controls the sequence of random values that are produced */
              0, /* the sequence number is only important with multiple cores */
              0, /* the offset is how much extra we advance in the sequence for each call, can be 0 */
              &state);

  /* curand works like rand - except that it takes a state as a parameter */
  *result = curand(&state) % MAX;
}

int main( ) {
  /* allocate an int on the GPU */
  int* gpu_x;
  cudaMalloc((void**) &gpu_x, sizeof(int));

  /* invoke the GPU to initialize all of the random states */
  random<<<1, 1>>>(time(NULL), gpu_x);

  /* copy the random number back */
  int x;
  cudaMemcpy(&x, gpu_x, sizeof(int), cudaMemcpyDeviceToHost);

  printf("Random number = %d.\n", x);

  /* free the memory we allocated */
  cudaFree(gpu_x);

  return 0;
}

Using Random Numbers Across Cores

If we want to get random numbers in multiple GPU cores, then we would need each core to have its own curandState_t.

If we want each run of the program to produce different sequences of random numbers, then we would need to set the seed to the current time.

However, now we would likely have each core get the same sequence of numbers. This is probably undesirable. To avoid it, we set the sequence parameter to the thread’s ID.

This way, each thread will have a different stream of random numbers, which will also be different each time the program is run.

The following program illustrates this by creating N curandState_t objects, then launching a GPU kernel to get N random numbers from them, in parallel.

#include <unistd.h>
#include <stdio.h>

/* we need these includes for CUDA's random number stuff */
#include 
#include 

#define N 25

#define MAX 100

/* this GPU kernel function is used to initialize the random states */
__global__ void init(unsigned int seed, curandState_t* states) {

  /* we have to initialize the state */
  curand_init(seed, /* the seed can be the same for each core, here we pass the time in from the CPU */
              blockIdx.x, /* the sequence number should be different for each core (unless you want all
                             cores to get the same sequence of numbers for some reason - use thread id! */
              0, /* the offset is how much extra we advance in the sequence for each call, can be 0 */
              &states[blockIdx.x]);
}

/* this GPU kernel takes an array of states, and an array of ints, and puts a random int into each */
__global__ void randoms(curandState_t* states, unsigned int* numbers) {
  /* curand works like rand - except that it takes a state as a parameter */
  numbers[blockIdx.x] = curand(&states[blockIdx.x]) % 100;
}

int main( ) {
  /* CUDA's random number library uses curandState_t to keep track of the seed value
     we will store a random state for every thread  */
  curandState_t* states;

  /* allocate space on the GPU for the random states */
  cudaMalloc((void**) &states, N * sizeof(curandState_t));

  /* invoke the GPU to initialize all of the random states */
  init<<<n, 1="">>>(time(0), states);

  /* allocate an array of unsigned ints on the CPU and GPU */
  unsigned int cpu_nums[N];
  unsigned int* gpu_nums;
  cudaMalloc((void**) &gpu_nums, N * sizeof(unsigned int));

  /* invoke the kernel to get some random numbers */
  randoms<<<n, 1="">>>(states, gpu_nums);

  /* copy the random numbers back */
  cudaMemcpy(cpu_nums, gpu_nums, N * sizeof(unsigned int), cudaMemcpyDeviceToHost);

  /* print them out */
  for (int i = 0; i < N; i++) {
    printf("%u\n", cpu_nums[i]);
  }

  /* free the memory we allocated for the states and numbers */
  cudaFree(states);
  cudaFree(gpu_nums);

  return 0;
}

This program is also the first to use multiple GPU kernel functions.


Random Distributions

In addition to the curand function which, together with modular arithmetic, can return to us random integers from any range we wish, cuRAND provides functions to get floating point numbers from different distributions:

__device__ float curand_uniform (curandState_t *state)

__device__ float curand_normal (curandState_t *state)

curand_uniform returns a random number between 0.0 and 1.0 following a uniform distribution. This means that all floating point numbers in that range are equally likely to be produced.

curand_normal also returns a random number between 0.0 and 1.0, but it follows a normal distribution, meaning that the number 0.5 is more likely to be produced than numbers near 0.0 or 1.0. Normal distributions would be important for modelling many natural phenomenon accurately.

Posted in CUDA TUTORIALS, GPU (CUDA), PARALLEL | Tagged: | Leave a Comment »

Bilateral Filtering

Posted by Hemprasad Y. Badgujar on September 14, 2015


Popular Filters

When smoothing or blurring images (the most popular goal of smoothing is to reduce noise), we can use diverse linear filters, because linear filters are easy to achieve, and are kind of fast, the most used ones are Homogeneous filter, Gaussian filter, Median filter, et al.

When performing a linear filter, we do nothing but output pixel’s value g(i,j)  which is determined as a weighted sum of input pixel values f(i+k, j+l):

g(i, j)=SUM[f(i+k, j+l) h(k, l)];

in which, h(k, l)) is called the kernel, which is nothing more than the coefficients of the filter.

Homogeneous filter is the most simple filter, each output pixel is the mean of its kernel neighbors ( all of them contribute with equal weights), and its kernel K looks like:

1

 Gaussian filter is nothing but using different-weight-kernel, in both x and y direction, pixels located in the middle would have bigger weight, and the weights decrease with distance from the neighborhood center, so pixels located on sides have smaller weight, its kernel K is something like (when kernel is 5*5):

gkernel

Median filter is something that replace each pixel’s value with the median of its neighboring pixels. This method is great when dealing with “salt and pepper noise“.

Bilateral Filter

By using all the three above filters to smooth image, we not only dissolve noise, but also smooth edges, which make edges less sharper, even disappear. To solve this problem, we can use a filter called bilateral filter, which is an advanced version of Gaussian filter, it introduces another weight that represents how two pixels can be close (or similar) to one another in value, and by considering both weights in image,  Bilateral filter can keep edges sharp while blurring image.

Let me show you the process by using this image which have sharp edge.

21

 

Say we are smoothing this image (we can see noise in the image), and now we are dealing with the pixel at middle of the blue rect.

22   23

Left-above picture is a Gaussian kernel, and right-above picture is Bilateral filter kernel, which considered both weight.

We can also see the difference between Gaussian filter and Bilateral filter by these pictures:

Say we have an original image with noise like this

32

 

By using Gaussian filter, the image is smoother than before, but we can see the edge is no longer sharp, a slope appeared between white and black pixels.

33

 

However, by using Bilateral filter, the image is smoother, the edge is sharp, as well.

31

OpenCV code

It is super easy to make these kind of filters in OpenCV:

1 //Homogeneous blur:
2 blur(image, dstHomo, Size(kernel_length, kernel_length), Point(-1,-1));
3 //Gaussian blur:
4 GaussianBlur(image, dstGaus, Size(kernel_length, kernel_length), 0, 0);
5 //Median blur:
6 medianBlur(image, dstMed, kernel_length);
7 //Bilateral blur:
8 bilateralFilter(image, dstBila, kernel_length, kernel_length*2, kernel_length/2);

and for each function, you can find more details in OpenCV Documentation

Test Images

Glad to use my favorite Van Gogh image :

vangogh

 

From left to right: Homogeneous blur, Gaussian blur, Median blur, Bilateral blur.

(click iamge to view full size version :p )

kernel length = 3:

homo3 Gaussian3 Median3 Bilateral3

kernel length = 9:

homo9 Gaussian9 Median9 Bilateral9
kernel length = 15:

homo15 Gaussian15 Median15 Bilateral15

kernel length = 23:

homo23 Gaussian23 Median23 Bilateral23
kernel length = 31:

homo31 Gaussian31 Median31 Bilateral31
kernel length = 49:

homo49 Gaussian49 Median49 Bilateral49
kernel length = 99:

homo99 Gaussian99 Median99 Bilateral99

Trackback URL.

Posted in C, Image / Video Filters, Image Processing, OpenCV, OpenCV, OpenCV Tutorial | Leave a Comment »

Basic drawing examples of OpenCV

Posted by Hemprasad Y. Badgujar on July 20, 2015


Drawing a line

void line(Mat& img, Point pt1, Point pt2, const Scalar& color, int thickness=1, int lineType=8, int shift=0)
Parameters:

  • img – Image.
  • pt1 – First point of the line segment.
  • pt2 – Second point of the line segment.
  • color – Line color.
  • thickness – Line thickness.
  • lineType – Type of the line:
    • 8 (or omitted) – 8-connected line.
    • 4 – 4-connected line.
    • CV_AA – antialiased line.
  • shift – Number of fractional bits in the point coordinates.

Example 1: Drawing a line


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
using namespace cv;
int main( )
{   
  // Create black empty images
  Mat image = Mat::zeros( 400, 400, CV_8UC3 );
  
  // Draw a line
  line( image, Point( 15, 20 ), Point( 70, 50), Scalar( 110, 220, 0 ),  2, 8 );
  imshow("Image",image);
  waitKey( 0 );
  return(0);
}


Drawing a Circle

void circle(Mat& img, Point center, int radius, const Scalar& color, int thickness=1, int lineType=8, int shift=0)
Parameters:

  • img – Image where the circle is drawn.
  • center – Center of the circle.
  • radius – Radius of the circle.
  • color – Circle color.
  • thickness – Thickness of the circle outline, if positive. Negative thickness means that a filled circle is to be drawn.
  • lineType – Type of the circle boundary. See the line() description.
  • shift – Number of fractional bits in the coordinates of the center and in the radius value.

The function circle draws a simple or filled circle with a given center and radius.

Example 2: Drawing a Circle


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
using namespace cv;
int main( )
{   
  // Create black empty images
  Mat image = Mat::zeros( 400, 400, CV_8UC3 );
  
  // Draw a circle
  circle( image, Point( 200, 200 ), 32.0, Scalar( 0, 0, 255 ), 1, 8 );
  imshow("Image",image);
  waitKey( 0 );
  return(0);
}


Drawing an Ellipse

void ellipse(Mat& img, Point center, Size axes, double angle, double startAngle, double endAngle, const Scalar& color, int thickness=1, int lineType=8, int shift=0)
Parameters:

  • img – Image.
  • center – Center of the ellipse.
  • axes – Length of the ellipse axes.
  • angle – Ellipse rotation angle in degrees.
  • startAngle – Starting angle of the elliptic arc in degrees.
  • endAngle – Ending angle of the elliptic arc in degrees.
  • box – Alternative ellipse representation via RotatedRect or CvBox2D. This means that the function draws an ellipse inscribed in the rotated rectangle.
  • color – Ellipse color.
  • thickness – Thickness of the ellipse arc outline, if positive. Otherwise, this indicates that a filled ellipse sector is to be drawn.
  • lineType – Type of the ellipse boundary. See the line() description.
  • shift – Number of fractional bits in the coordinates of the center and values of axes.

The functions ellipse with less parameters draw an ellipse outline, a filled ellipse, an elliptic arc, or a filled ellipse sector. A piecewise-linear curve is used to approximate the elliptic arc boundary.

If you use the first variant of the function and want to draw the whole ellipse, not an arc, passstartAngle=0 and endAngle=360.

Example 3: Drawing an Ellipse


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
using namespace cv;
int main( )
{   
  // Create black empty images
  Mat image = Mat::zeros( 400, 400, CV_8UC3 );
  
  // Draw a ellipse
  ellipse( image, Point( 200, 200 ), Size( 100.0, 160.0 ), 45, 0, 360, Scalar( 255, 0, 0 ), 1, 8 );
  ellipse( image, Point( 200, 200 ), Size( 100.0, 160.0 ), 135, 0, 360, Scalar( 255, 0, 0 ), 10, 8 );
  ellipse( image, Point( 200, 200 ), Size( 150.0, 50.0 ), 135, 0, 360, Scalar( 0, 255, 0 ), 1, 8 );
  imshow("Image",image);
  waitKey( 0 );
  return(0);
}


Drawing a Rectangle

void rectangle(Mat& img, Point pt1, Point pt2, const Scalar& color, int thickness=1, int lineType=8, int shift=0)
Parameters:

  • img – Image.
  • pt1 – Vertex of the rectangle.
  • pt2 – Vertex of the rectangle opposite to pt1 .
  • rec – Alternative specification of the drawn rectangle.
  • colorRectangle color or brightness (grayscale image).
  • thickness – Thickness of lines that make up the rectangle. Negative values, likeCV_FILLED , mean that the function has to draw a filled rectangle.
  • lineType – Type of the line. See the line() description.
  • shift – Number of fractional bits in the point coordinates.

Example 4: Drawing a Rectangle


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
using namespace cv;
int main( )
{   
  // Create black empty images
  Mat image = Mat::zeros( 400, 400, CV_8UC3 );
  
  // Draw a rectangle ( 5th argument is not -ve)
  rectangle( image, Point( 15, 20 ), Point( 70, 50), Scalar( 0, 55, 255 ), +1, 4 );
  imshow("Image1",image);
  // Draw a filled rectangle ( 5th argument is -ve)
  rectangle( image, Point( 115, 120 ), Point( 170, 150), Scalar( 100, 155, 25 ), -1, 8 );
  imshow("Image2",image);
  waitKey( 0 );
  return(0);
}


Drawing a Filled Polygon

void fillPoly(Mat& img, const Point** pts, const int* npts, int ncontours, const Scalar& color, int lineType=8, int shift=0, Point offset=Point() )
Parameters:

  • img – Image.
  • pts – Array of polygons where each polygon is represented as an array of points.
  • npts – Array of polygon vertex counters.
  • ncontours – Number of contours that bind the filled region.
  • color – Polygon color.
  • lineType – Type of the polygon boundaries. See the line() description.
  • shift – Number of fractional bits in the vertex coordinates.
  • offset – Optional offset of all points of the contours.

The function fillPoly fills an area bounded by several polygonal contours. The function can fill complex areas, for example, areas with holes, contours with self-intersections (some of their parts), and so forth.

Example 4: Drawing a Filled Polygon


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
using namespace cv;
int main( )
{   
  // Create black empty images
  Mat image = Mat::zeros( 400, 400, CV_8UC3 );
  
  int w=400;
  // Draw a circle
  /** Create some points */
  Point rook_points[1][20];
  rook_points[0][0] = Point( w/4.0, 7*w/8.0 );
  rook_points[0][1] = Point( 3*w/4.0, 7*w/8.0 );
  rook_points[0][2] = Point( 3*w/4.0, 13*w/16.0 );
  rook_points[0][3] = Point( 11*w/16.0, 13*w/16.0 );
  rook_points[0][4] = Point( 19*w/32.0, 3*w/8.0 );
  rook_points[0][5] = Point( 3*w/4.0, 3*w/8.0 );
  rook_points[0][6] = Point( 3*w/4.0, w/8.0 );
  rook_points[0][7] = Point( 26*w/40.0, w/8.0 );
  rook_points[0][8] = Point( 26*w/40.0, w/4.0 );
  rook_points[0][9] = Point( 22*w/40.0, w/4.0 );
  rook_points[0][10] = Point( 22*w/40.0, w/8.0 );
  rook_points[0][11] = Point( 18*w/40.0, w/8.0 );
  rook_points[0][12] = Point( 18*w/40.0, w/4.0 );
  rook_points[0][13] = Point( 14*w/40.0, w/4.0 );
  rook_points[0][14] = Point( 14*w/40.0, w/8.0 );
  rook_points[0][15] = Point( w/4.0, w/8.0 );
  rook_points[0][16] = Point( w/4.0, 3*w/8.0 );
  rook_points[0][17] = Point( 13*w/32.0, 3*w/8.0 );
  rook_points[0][18] = Point( 5*w/16.0, 13*w/16.0 );
  rook_points[0][19] = Point( w/4.0, 13*w/16.0) ;
  const Point* ppt[1] = { rook_points[0] };
  int npt[] = { 20 };
  fillPoly( image, ppt, npt, 1, Scalar( 255, 255, 255 ), 8 );
  imshow("Image",image);
  waitKey( 0 );
  return(0);
}


Putting Text in image

putText renders the specified text string in the image.

void putText(Mat& img, const string& text, Point org, int fontFace, double fontScale, Scalar color, int thickness=1, int lineType=8, bool bottomLeftOrigin=false )
Parameters:

  • img – Image.
  • text – Text string to be drawn.
  • org – Bottom-left corner of the text string in the image.
  • fontFace – Font type. One of FONT_HERSHEY_SIMPLEX, FONT_HERSHEY_PLAIN,FONT_HERSHEY_DUPLEX, FONT_HERSHEY_COMPLEX, FONT_HERSHEY_TRIPLEX,FONT_HERSHEY_COMPLEX_SMALL, FONT_HERSHEY_SCRIPT_SIMPLEX, orFONT_HERSHEY_SCRIPT_COMPLEX, where each of the font ID’s can be combined withFONT_HERSHEY_ITALIC to get the slanted letters.
  • fontScale – Font scale factor that is multiplied by the font-specific base size.
  • color – Text color.
  • thickness – Thickness of the lines used to draw a text.
  • lineType – Line type. See the line for details.
  • bottomLeftOrigin – When true, the image data origin is at the bottom-left corner. Otherwise, it is at the top-left corner.

Example 5: Putting Text in image


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
using namespace cv;
int main( )
{
  // Create black empty images
  Mat image = Mat::zeros( 400, 400, CV_8UC3 );
  
  putText(image, "Hi all...", Point(50,100), FONT_HERSHEY_SIMPLEX, 1, Scalar(0,200,200), 4);
  imshow("Image",image);
  waitKey( 0 );
  return(0);
}

Posted in Mixed | Tagged: | Leave a Comment »

cppconlib: A C++ library for working with the Windows console

Posted by Hemprasad Y. Badgujar on July 20, 2015


cppconlib is built with C++11 features and requires Visual Studio 2012 or newer. The library is available in a single header called conmanip.h and provides a set of helper classes, functions and constants for manipulating a Windows console (using the Windows console functions). The library features the following components:

  • console_context<T>: represents a context object for console operations; its main purpose is restoring console settings; typedefs for the three consoles are available (console_in_context, console_out_context and console_err_context)
  • console<T>: represents a console objects providing operations such as changing the foreground and background colors, the input mode, screen buffer size, title, and others; typedefs for the three consoles are available (console_in, console_out and console_err)
  • manipulating functions that can be used with cout/wcout and cin/wcin: settextcolor()/restoretextcolor(), setbgcolor()/restorebgcolor(), setcolors(),setmode()/clearmode(), setposx()/setposy()/setpos().

The library can be downloaded from here. Detailed documentation is available here.

cppconlib

Examples

The following example prints some text in custom colors and then reads text in a different set of colors.

cppconlib2

The following code prints a rhomb to the console:

cppconlib3

For more details and updates check the project at codeplex: https://cppconlib.codeplex.com.

UPDATE: A NuGet package for cppconlib is available.

Posted in Computer Software, Computer Vision | Tagged: , , , , , | Leave a Comment »

OpenCV: Color-spaces and splitting channels

Posted by Hemprasad Y. Badgujar on July 18, 2015


Conversion between color-spaces

Our goal here is to visualize each of the three channels of these color-spaces: RGB, HSV, YCrCb and Lab. In general, none of them are absolute color-spaces and the last three (HSV, YCrCb and Lab) are ways of encoding RGB information. Our images will be read in BGR (Blue-Green-Red), because of OpenCV defaults. For each of these color-spaces there is a mapping function and they can be found at OpenCV cvtColor documentation.
One important point is: OpenCV imshow() function will always assume that the Mat shown is in BGR color-space. Which means, we will always need to convert back to see what we want. Let’s start.

OpenCV Program: Split Channels (356 downloads )

HSV

While in BGR, an image is treated as an additive result of three base colors (blue, green and red), HSV stands for Hue, Saturation and Value (Brightness). We can say that HSV is a rearrangement of RGB in a cylindrical shape. The HSV ranges are:

  • 0 > H > 360 ⇒ OpenCV range = H/2 (0 > H > 180)
  • 0 > S > 1 ⇒ OpenCV range = 255*S (0 > S > 255)
  • 0 > V > 1 ⇒ OpenCV range = 255*V (0 > V > 255)

YCrCb or YCbCr

It is used widely in video and image compression schemes. The YCrCb stands for Luminance (sometimes you can see Y’ as luma), Red-difference and Blue-difference chroma components. The YCrCb ranges are:

  • 0 > Y > 255
  • 0 > Cr > 255
  • 0 > Cb > 255

L*a*b

In this color-opponent space, L stands for the Luminance dimension, while a and b are the color-opponent dimensions. The Lab ranges are:

  • 0 > L > 100 ⇒ OpenCV range = L*255/100 (1 > L > 255)
  • -127 > a > 127 ⇒ OpenCV range = a + 128 (1 > a > 255)
  • -127 > b > 127 ⇒ OpenCV range = b + 128 (1 > b > 255)

Splitting channels

All the color-spaces mentioned above were constructed using three channels (dimensions). It is a good exercise to visualize each of these channels and realize what they really store, because when I say that the third channel of HSV stores the brightness, what do you expect to see? Remember: a colored image is made of three-channels (in our cases) and when we see each of them separately, what do you think the output will be? If you said a grayscale image, you are correct! However, you might have seen these channels as colored images out there. So, how? For that, we need to choose a fixed value for the other two channels. Let’s do this!
To visualize each channel with color, I used the same values used on the Slides 53 to 65 from CS143, Lecture 03 from Brown University.

RGB or BGR

Original image (a) and its channels with color: blue (b), green (c) and red (d). On the second row, each channel in grayscale (single channel image), respectively.

HSV

Original image (a) and its channels with color: hue (b), saturation (c) and value or brightness (d). On the second row, each channel in grayscale (single channel image), respectively.

YCrCb or YCbCr

Original image (a) and its channels with color: luminance (b), red-difference (c) and blue difference (d). On the second row, each channel in grayscale (single channel image), respectively.

Lab or CIE Lab

Original image (a) and its channels with color: luminance (b), a-dimension (c) and b-dimension (d). On the second row, each channel in grayscale (single channel image), respectively.

Posted in Computer Vision, GPU (CUDA), OpenCV, OpenCV, OpenCV Tutorial | Tagged: , , | Leave a Comment »

Bulk Rename Utility

Posted by Hemprasad Y. Badgujar on July 18, 2015


These file rename software let you rename multiple files easily. All these file rename software are completely free and can be downloaded to Windows PC. These file rename softwareoffer various features, like: rename multiple files at once,rename files as well as folders including sub-folders, can add, remove, replace strings to file names, can copy and rename, move and rename files, supports all types of files (including images, audio/video, office documents etc.), rename files based upon their EXIF data or meta data, and more. Check out this list of free file rename software and find out which you like best.

File Renamer Basic

File Renamer Basic is a simple yet powerful program to rename files, folders, and MP3 files easily. You can use its filename filter to easily narrow down your search for specific types of files. You can remove x number of characters starting from x character. You can find and replace text also. Apart from its renaming capabilities, it also has a ID3v1 and ID3v2 tag editor.

Home Page     Download Page

Flexible Renamer

Flexible Renamer is a free and easy to use software for renaming files and folders. You can rename files and folders in single or in batches. It doesn’t require installation as it is a portable application. You can use its simple or advanced rename method to rename your files and folders. You can copy and rename, move and rename, move to recycle bin and can use other various methods too. It supports wildcards also when renaming.

Home Page     Download Page

Advanced Renamer

Advanced Renamer is a free software for renaming files or folders. It uses various methods for creating the new names. It can create new file names by adding, removing, replacing, giving new name based upon the file information, or changing case. You can test the batch settings before you start renaming. It is also available in portable version.

Home Page     Download Page

BatchRename Free Edition

BatchRename Free is a free files and folders renaming software. It uses two steps to rename files and folders. In step one you can add files and folders to rename and in second step you can set rules for renaming according to your requirements. It has various predefined rules for various types of files. It has some image editing features also, like change format, flip, rotate, resize, shrink etc. You can preview renaming. It installs and uninstalls easily.

Home Page     Download Page

Bulk Rename Utility


Bulk Rename Utility is a free utility to rename files and folders with flexible criteria. It can process sub folders, can add date stamps, auto numbers, search and replace, change time stamps etc. It offers 13 primary functions to rename. It can handle file attributes, metadata, and sophisticated regular expressions. You can preview file names before you actually start renaming. This software is for power users.

Home Page     Download Page

Batch File Modifier

Batch File Modifier is a multipurpose software and it also has the functionality of renaming files and folders. It has a wizard like interface. You can set the naming options from the options window and can use the various tabs according to your requirement of renaming. You can add prefix or suffix to file names. You can preview file names also in this window. You can undo the rename process also.

Home Page     Download Page

XnView


XnView is actually a multi format graphics browser, viewer, and converter, but it also has the functionality of renaming files. It has an Explorer like interface. You can browse for folder whose files have to be renamed and select the files to be renamed. Select the batch rename option from the context menu. Set the rename options from the interface according to your choice. You can view the new name of files in real time. On satisfying the new names start the rename process by clicking on Rename button.

Home Page     Download Page

ReNamer

ReNamer is a simple file renaming tool. It lets you rename files and folders according to standard renaming procedures, including case changes, prefixes, suffixes, replacements, adding number sequences etc. Also supports changing of file extensions. You can add the rules before you start renaming. This software is for beginners as well as for advance users.

Home Page     Download Page

IrfanView

IrfanView is a simple, small, fast, compact and innovative free graphic viewer software and also has the functionality of renaming files. You can use it to rename files from any specified folder and its subfolders. You can set the rename options before you start renaming. You can also preview the batch rename results. You can see the errors and warnings in the preview mode. It is a very simple and easy to use software to rename the files.

Home Page     Download Page

Rename It

Rename It is a simple file renaming utility specifically designed for new computer users. It lets you rename a file or a file extension easily. It has an option of massive rename which lets you rename multiple files or extensions easily. If there is a common text in the name of files, it can be easily renamed with the help of it.

Home Page     Download Page

Effective File Search

Effective File Search is actually a file searching utility and also has a function of renaming files. You can use it to rename the filenames to either lowercase or uppercase only. To use it, first browse for a folder from which files have to be renamed by using its browse button. You can include sub directories also in the search. Now search for all files or for any particular format. Select the files from the results and select rename files options from the Actions menu.

Home Page     Download Page

Ken Rename

Ken Rename is a free batch file renaming utility. It has various configuration options to rename files. Some of its features include: filter files with wildcard, convert to lowercase or uppercase, replace particular text from names, insert digit and increment options, EXIF support etc. You can view the real time preview of renamed files before actually renaming. It is for beginners as well as for advance users.

Home Page     Download Page

PhotoRenamer

PhotoRenamer is a free software which lets you rename your digital photos according to the date and the time you took the pictures. It uses date and time or EXIF Data for renaming or you can use renaming masks. Renaming masks are format specifications stings for e.g. day, month, year, hour, min, sec, photo number and free text. Note: If you choose file selection filter as ., then you can rename any type of file according to renaming mask you use.

Home Page     Download Page

Image Renaming

Image Renaming is a free software to rename image files. You can rename image files based on date and time criteria. You can choose from various predefined formats or can customize your own. It comes as a ZIP file and you can extract it to the desired location and run it. It doesn’t require installation and can be used as a portable software. It is very small in size.

Home Page     Download Page

Panda Batch File Renamer

Panda Batch File Renamer is a free file renaming software. It lets you rename files in batch mode. You can choose from various rename options. You can use its insert, replace, remove, and other categories of renaming options. It shows the current file name and final file names side by side. You can add multiple renaming options and they can be queued. It stores the history of changes so you can undo the rename process if required.

Home Page     Download Page

Aoao Batch Rename

Aoao Batch Rename is free and easy to use file renaming software. You can rename multiple files at once. You can rename all file formats. It is good for renaming image files. You can set the file names with increasing alphabet or digit. This software can be used for simple renaming tasks.

Home Page     Download Page

RenPhoric

RenPhoric is a simple and easy to use batch renaming software. It is good for search and replace text in the file names. You can include subdirectories too for renaming files. It allows you to use regular expressions for renaming process. It is a great choice for you to batch rename images, songs, or any other files that are big in numbers.

Home Page     Download Page

Rename JPEG Files

Rename JPEG Files is a free software to rename JPG files in bulk quantity. It uses predefined file naming formats. You can drag and drop files to its window or specify a target directory that contains JPG files. It also displays the information about JPG files selected, such as name, creation date, resolution etc. It shows the file names before and after side by side. You can build the name format or use the default format.

Home Page     Download Page

File Renamer

File Renamer is a free and handy software to rename multiple files at once. You can batch rename files, add or remove text strings from file names, can change file extensions, add numbers sequentially to file names, change to upper case or lowercase, trim characters etc. It also has an undo option for last rename process. It doesn’t require installation and can be used as a portable software.

Home Page     Download Page

FMS File Renamer

FMS File Renamer is a simple and useful tool to rename files. It has various features to rename files. You can try various combinations for renaming the files. You can add strings to prefix, suffix, or at a position you choose in the resultant file names. You can delete, replace, change case (upper of lower), move/copy etc. in one go. You can preview every step by clicking green check mark. The program is suitable for any type of user (newbie or advance).

Home Page     Download Page

Rename Master

Rename Master is a free software to rename multiple files with few clicks. It is a simple tool to rename multiple files easily. It has 15 types of rename options and you can configure each of them separately. It lets you add, remove, or replace strings to file names easily. You can rename folders too with this utility. It also supports scripts to save the renaming options. It doesn’t require installation.

Home Page     Download Page

Batch Rename .EXE

Batch Rename .EXE is a free software to rename multiple files at once. It can rename files in four easy steps in a wizard like interface. You can add files or folders to rename in step one. In step two set the rules for renaming. You can preview the results in the step three and finally rename them in step four. It can include the metadata in the names of files for renaming.

Home Page     Download Page

A.F.5 Rename your files

A.F.5 Rename your files is a free software to rename files easily. It has various features including drag & drop support, preview before renaming, undo last rename action, create batch program files, save rename settings, import filenames from a text file. You can apply multiple types of values to the file names for renaming like text string, size, digit counter, metadata etc. You can undo the last rename changes also by clicking again on rename button.

Home Page     Download Page

File Renamer

File Renamer is a free software for renaming multiple files at once. It can be used to rename images as well as all types of files. You can use file mask to filter files of specific type (for e.g. *.png). You can set the new name with incremental digit. It also has an option to move the renamed files to a different folder.

Home Page     Download Page

Fast File Renamer

Fast File Renamer is a free software to rename files based upon criteria you choose. You can replace, remove, or insert strings to file names. It has a simulate function which lets you preview the files before you actually rename. When satisfied with the new name, click undo simulate button and click perform rename button to rename files. It can be used as portable software.

Home Page     Download Page

Lupas Rename

Lupas Rename is a free and easy to use software to rename multiple files. You can rename folders too. Files in the sub directories can also be renamed. It also supports undo last rename operation. You can filter files for any particular type using wildcards. You can apply multiple options together (name, extension, and auto number) in the rename process. It shows the real time preview of results.

Home Page     Download Page

Wild Rename

Wild Rename is a very simple and easy to use file renaming utility. You can perform the task of renaming files with regular expressions. It doesn’t require installation and can be used as a portable software. It can help you to rename file names by converting lower case, upper case, or normal case. You can add strings to file names, replace specific text from file names, add counters etc.

Home Page     Download Page

Siren

Siren is a free, small but powerful renaming tool for Windows. It is for normal users as well as for power users. You can use it to rename multiple files and folders. It uses expressions for renaming process. You can build your own customized naming expression by using help. It doesn’t require installation and can be used as a portable software.

Home Page     Download Page

MP3 Rename

MP3 Rename is a free utility to rename MP3 files easily. It can rename MP3 files according to rules that you specify. You can replace the text with your text from the names of MP3 files. It doesn’t require installation and can be used as a portable software. You can add ID3 v2 tags to file names. You can move files into folders according to artist name also. It is a good software to rename MP3 files.

Home Page     Download Page

Ant Renamer

Ant Renamer is a very useful multiple files and folders renaming software. It can rename multiple files, folders with sub-folders and sub-files. It can also rename multiple strings from the file and folder name. Actually, this software provides dozens of file renaming features, some of them are: Move string, String insertion, Change case, Use date & time, Enumeration, etc. This small size portable software is one of the best file renaming software.

Home Page     Download Page

AS-File Renamer

AS-File Renamer is a free software for renaming files. It renames files by providing serial numbers to them. Suppose you capture a snapshot with your camera. Then you can rename the snapshots as abc 1, abc 2, abc 3. If you want to rename your files according to serial numbers then you can try out this freeware.

Home Page     Download Page

LeCase

LeCase is a free and handy file renamer software for your computer. With the help of this freeware you can easily rename all files in a particular directory to lowercase names or uppercase names. By using this freeware you can also rename your picture files in a directory by specifying various numbers to it. e.g x1, x2, x3 etc.

Home Page     Download Page

File Renamex

File Renamex is a free file renamer software to rename files quickly. With the help of this freeware you can rename files in a easy manner. You can rename any type of file e.g. video, audio, picture, document etc. This freeware lets you do file renaming in bulk. It will rename files as per numbering format and prefix.

Home Page     Download Page

KuKnet FileRenamer

KuKnet FileRenamer is a free software for renaming multiple files. It is a powerful tool for renaming files. You can add files or folders by click of a button or by drag and drop to its window. It shows the preview of image files. You can set rules for renaming files and can save them for future use. You can use search and replace, numeration, add file size, date/time, ID3 tag etc. to rename file names. It comes as a single executable and doesn’t require installation.

Home Page     Download Page

EXIF Image Renamer

EXIF Image Renamer is a simple tool for renaming image files based upon their EXIF data. You can select the folder with images to rename by browsing for its location through the program interface. It does not have preview facility so new file names will change according to EXIF data present. It renames the images in sub folders too.

Home Page     Download Page

Batch Rename

Batch Rename is an easy to use but powerful renaming tool for Windows. It lets you rename files and folders according to the rules you set. You can add single rule or combine multiple rules for renaming. For e.g. you can prefix or suffix any text to file names, add counter at specific position, remove strings etc. to the file names. You can also preview the file names before renaming.

Home Page     Download Page

MP3 Renamer

MP3 Renamer is a free tool for renaming large amount of MP3 files. It has various predefined presets for renaming MP3 files like remove extra hyphens, change to sentence case, remove URLs, remove dots, change to upper case etc. You can rename MP3 files based upon their ID3 tags values also. It has a inbuilt MP3 player also.

Home Page     Download Page

Tiny Renamer

Tiny Renamer is a very small and easy to use file renaming utility. You can rename multiple files easily. You can shorten long file names, use simple regular expression or advance regular expression for renaming. You can rename file extension too with the help of it. It has a replace and replace with text box in its main window. It is a good choice for renaming multiple MP3 files.

Home Page     Download Page

JFRenamer

JFRenamer is a free file and folder renaming software. It lets you rename the files and folders according to rules you set. You can add multiple rules to the list for renaming. You can configure each rule separately according to the requirement. You can set various rules like change case, replace, delete, insert, if/else etc. The software is written in JAVA and JAVA must be installed on the system to use it.

Home Page     Download Page

Bica File Renamer

Bica File Renamer is a simple and easy to use file renaming utility. It lets you rename files and folders with few clicks. You can apply many different rename options like search and replace, change case, sequential numbering, insert, remove, date/time etc. It is small in size and doesn’t require installation. You can use it as a portable software too.

Home Page     Download Page

Infinite Dreamers FileRenamer

Infinite Dreamers FileRenamer is a free software to rename multiple files at once. To rename files you have to navigate to the directory whose files you want to rename. You can select all files at once from any directory using context menu. You can replace old name containing text string with new text string easily. You can add multiple replace strings simultaneously.

Home Page     Download Page

Rename Us Pro

Rename Us Pro is a free file renaming utility for Windows. It lets you rename files in batch mode. You can set various options for renaming. You can add multiple rules for renaming like change case, enumeration, adding prefix or suffix to file names, using MP3 tags, file date etc. You can run it in the test mode to check the results before actually renaming.

Home Page     Download Page

Renamer

Renamer is a free and simple file renaming software for Windows. It is very tiny in size but a useful file renaming tool. It has various functions to rename files. You can use its replace with space, search and replace, line by line replace, insert text at position, remove text by position and other various functions to rename files.

Home Page     Download Page

UltimateReNamerJG

UltimateReNamerJG is a small, simple, and easy to use rename tool for Windows. It lets you batch rename multiple files at once. You can add multiple rules for renaming. With the help of it you can insert, delete, replace text strings from file names, can change extension, can change case, set incremental digits to specific position etc. It has a restore backup option if you accidently change file names.

Home Page     Download Page

FileNameStringReplacer

FileNameStringReplacer is simple file renaming utility. It lets you find and replace specific text string from file names. It doesn’t require installation and can be used as a portable software. You can select the folder whose files have to be renamed from the select button. Set the search string to find in file names and type the replace with string to start renaming. It is easy to use software.

Home Page     Download Page

RKrenamer

RKrenamer is a simple tool for renaming multiple files at once. You can rename large number of files in one go. You can insert text strings in file names, replace text, delete text, change case (upper/lower) or serialize the files. It also supports drag and drop feature. It has a simple and easy to use user interface.

Home Page     Download Page

Personal Renamer

Personal Renamer is a free renaming tool for Windows. It lets you rename multiple files in a folder easily. It is a powerful batch file renamer and supports numbering or lettering files etc. You have to set the source and destination directory (both can be same) before you start renaming. You can set the various renaming rules in the advanced menu. You can undo the rename mistakes too.

Home Page     Download Page

RenameApp

RenameApp is a free and easy to use file renaming software for Windows. It lets you easily rename files based upon the specified criteria and order. It supports drag and drop feature. You can preview rename results before you actually start the renaming process. You can add prefix or suffix to the file names, use specific names, can rename file extension etc.

Home Page     Download Page

SolidRenamer

SolidRenamer is a free and easy to use file renaming software for Windows. It lets you rename files easily. It supports various rules for renaming files including prefixes, suffixes, inserting of text, clipping, replace text, change case, enumerations etc. You can set multiple rules for renaming in a sequence. It also has a preview facility before actually starting renaming process.

Home Page     Download Page

File Batch Renamer

File Batch Renamer is a file renaming tool available free. You can rename multiple files or multiple types at once. You have to choose a common name, numbering style and separator to start renaming. You can select the output folder same or different from the source. It doesn’t have many options and is a simple file renaming tool.

Home Page     Download Page

LuJoSoft Rename-All

LuJoSoft Rename-All is a simple and easy to use application to rename files. Some of its features includes add text to file names, remove text from file names, replace text, change case as uppercase or lowercase, capitalize each word etc. It has a preview option also. It shows the renamed files and original file names side by side.

Home Page     Download Page

PSRenamer

PSRenamer is an open source program to rename files in batch mode. It lets you change any part of file name or its extension. You can add sequential numbers to file names. It has preview and undo functions also. As it is a JAR file and JAVA must be installed on the system to use it. It is small in size and can be used as a portable software.

Home Page     Download Page

Daanav File Renamer

Daanav File Renamer is a free software to rename multiple files at once. It lets you rename various files with one click. You can find and replace text in the filenames, add incremental numbers, remove characters up to length you specify, change case (upper or lower) etc. to the file names. It is easy to use and has a user friendly interface.

Home Page     Download Page

Posted in Computer Research, Computer Softwares, Entertainment | Tagged: , , | Leave a Comment »

 
Num3ri v 2.0

I miei numeri - seconda versione

ThuyDX

Just another WordPress.com site

josephdung

thoughts...

Algunos Intereses de Abraham Zamudio Chauca

Matematica, Linux , Programacion Serial , Programacion Paralela (CPU - GPU) , Cluster de Computadores , Software Cientifico

Tech_Raj

A great WordPress.com site

Travel tips

Travel tips

Experience the real life.....!!!

Shurwaat achi honi chahiye ...

Ronzii's Blog

Just your average geek's blog

Karan Jitendra Thakkar

Everything I think. Everything I do. Right here.

VentureBeat

News About Tech, Money and Innovation

Chetan Solanki

Helpful to u, if u need it.....

ScreenCrush

Explorer of Research #HEMBAD

managedCUDA

Explorer of Research #HEMBAD

siddheshsathe

A great WordPress.com site

Ari's

This is My Space so Dont Mess With IT !!

Business India 2.0

All about Business Travel 2.0 ideas,technology,ventures and the capital making its happen

Something More for Research

Explorer of Research #HEMBAD

Follow

Get every new post delivered to your Inbox.

Join 4,846 other followers

%d bloggers like this: