Friday, September 6, 2024

Load huge amount of data in process 0 and use it in other processes with shared_memory

It happens that when we create multiprocesses say a node with 8XA100 GPUs that each process has a copy of data, which easily goes beyond the memory limit of the whole node. Instead, we could let the rank 0 load data and the rest wait until it is ready. The code is given as follows,

import time
import pickle
import numpy as np
from multiprocessing import shared_memory

# dummy data to load
data = [{"url": "xxx", "exp": "yyy"}] * 20

# serialize
data = [pickle.dumps(d) for d in data]

# process 0
if rank % 8 == 0:
	shm_a = shared_memory.ShareableList(data, name='shared_data')
    print(pickle.loads(shm_a[0]))
# other processes
else:
    while True:
        try:
            shm_b = shared_memory.ShareableList(name="shared_data")
            print(f"Attached to shared memory with name: shared_data")
            print(pickle.loads(shm_b[0]))
            break
        except FileNotFoundError:
            print("Shared memory not found. It may not be created yet.")
            time.sleep(100)

Saturday, December 3, 2022

Is Lanzhou City the mass center of the map of China?

Almost!

It turns out that blue (Lanzhou city) is close to but not exact the mass center (red). I mean, if we only consider Lanzhou as a point.

An algorithmic approach

import json
import matplotlib.pyplot as plt
from matplotlib.patches import Polygon
import numpy as np
import cv2

# be aware to fix coordinates from 内蒙古 (add an extra bracket, download it from https://geo.datav.aliyun.com/areas_v3/bound/100000_full.json)
with open('100000_full.json', 'r') as f:
    content = json.load(f)

print(content.keys())


fig, ax = plt.subplots()

for feat in content['features']:
    if feat['properties']['name'] == '甘肃省':
        center = feat['properties']['center']
    if feat['properties']['name'] not in ['']:
        coordinates = feat['geometry']['coordinates']
        for c in coordinates:
            coord = np.array(c)
            if len(coord[0].shape) == 2:
                p = Polygon(coord[0], facecolor='k')
                ax.add_patch(p)
            else:
                print(coord[0])
                print(feat['properties']['name'])

ax.set_xlim([60, 140])
ax.set_ylim([0, 60])
cx, cy = center
print("center", center)
print("lim:", ax.get_xlim(), ax.get_ylim())
xmin, xmax = ax.get_xlim()
ymin, ymax = ax.get_ylim()
cx = (cx -60) * (640 / (xmax - xmin))
cy = 480 - cy * (480 / (ymax-ymin))
print("center scaled:", cx, cy)
plt.axis('off')
plt.tight_layout()
plt.savefig("china_map.png")
plt.show()


img = cv2.imread('china_map.png', 0)
print(img.shape, img.mean(), img.max(), img.min())
th, im_th = cv2.threshold(img, 100, 255, cv2.THRESH_BINARY_INV)

print(th)
print(im_th.shape)
cv2.imwrite('china_map_inverse.png', im_th)

moments = cv2.moments(im_th, True)
print(moments)

centeroid = (moments['m10'] / moments['m00'], moments['m01'] / moments['m00'])
print("centeroid:", centeroid)
x,y = centeroid
fig,ax = plt.subplots()

img = cv2.imread('china_map.png')
ax.imshow(img)

plt.scatter(x, y, c='r')
plt.scatter(cx, cy, c='b')
plt.tight_layout()
plt.axis('off')
plt.savefig('china_map_with_centeroid.png')
plt.show()

References

  • https://blog.csdn.net/qq826309057/article/details/70039397
  • https://www.zhoulujun.cn/html/GIS/WebGIS/8348.html
  • http://datav.aliyun.com/portal/school/atlas/area_selector#&lat=33.50475906922609&lng=104.2822265625&zoom=4

Sunday, September 20, 2020

Python: Find and Delete Corrupted Audio Files

import os
import wave
import glob

def compare_header_and_size(wav_filename):
    with wave.open(wav_filename, 'r') as fin:
            header_fsize = (fin.getnframes() * fin.getnchannels() * fin.getsampwidth()) + 44
    file_fsize = os.path.getsize(wav_filename)
    return header_fsize != file_fsize

print('The following files are corrupted:')
for f in  glob.glob("_background_noise_/*.wav"):
    if compare_header_and_size(f):
        print(f)
        os.remove(f)

Sunday, August 20, 2017

Bootstrap Footer Best Practice

see Sticky Footer

html {
    position: relative;
    min-height: 100%;
}
body {
    margin-bottom: 60px;
}
.footer{
    position: absolute;
    bottom: 0;
    width: 100%;
    height: 60px;
    line-height: 60px;
    background-color: #f5f5f5;
}

Tuesday, June 7, 2016

Setting up Ubuntu 15.04 + PHP5.6 + Nginx + MySQL + Laravel 5 + npm + Bower + Gulp

  1. install a brand new Ubuntu 15.04 amd64 version
  2. uname -a

     Linux jasler 3.19.0-15-generic #15-Ubuntu SMP Thu Apr 16 23:32:37 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux
  3. Setting root password

     sudo passwd root
     >> root
  1. check if apache2 is installed and port 80 is being used

     ps -A | grep apache
     sudo netstat -nlp  | grep 80

remove if installed:

    sudo killall apache2
    sudo apt-get remove apache2
  1. Install Nginx

     sudo apt-get install nginx
     nginx -v
         nginx version: nginx/1.6.2 (Ubuntu)
  2. Install MySQL

     sudo apt-get install mysql-server

It will also install mysql-client and other dependencies in the meantime.

Press Enter on seeing a blank terminal to proceed.

Set the root password root for this time.

  1. Install PHP5 and its extensions

     sudo apt-get install php5 php5-mcrypt php5-gd php5-mysql php5-fpm php5-curl

It also installs apache2 automatically, if it conflicts with nginx, we recommend to remove it.

Check the php and mysql version:

    php -v
    PHP 5.6.4-4ubuntu6.4 (cli) (built: Oct 28 2015 01:21:29) 
    Copyright (c) 1997-2014 The PHP Group
    Zend Engine v2.6.0, Copyright (c) 1998-2014 Zend Technologies
        with Zend OPcache v7.0.4-dev, Copyright (c) 1999-2014, by Zend Technologies
 
 
    mysql -p -uroot -v
    Enter password: 
    Welcome to the MySQL monitor.  Commands end with ; or \g.
    Your MySQL connection id is 4
    Server version: 5.6.28-0ubuntu0.15.04.1 (Ubuntu)
  1. Install npm

    sudo apt-get install npm
    npm -v
    1.4.21

update within it self:

    sudo npm install -g npm
    /usr/local/bin/npm -> /usr/local/lib/node_modules/npm/bin/npm-cli.js
    npm@3.8.3 /usr/local/lib/node_modules/npm

Or install this way:

    sudo apt-get install curl
    curl -sL https://deb.nodesource.com/setup > install.sh
    sudo chmod +x install.sh
    sudo ./install.sh
    sudo apt-get install nodejs
    sudo npm install -g npm
  1. Install git

    sudo apt-get install git
  2. Creating dev folder:

change usr to your account

    sudo mkdir /home/wwwroot/
    sudo chown -R [usr].[usr] /home/wwwroot
  • Cloning repo:

    cd /home/wwwroot/
    git clone ssh://git@yourrepo.com:/home/git/yourrepo.git
  • npm install (within vpn)

    sudo npm install
  • Install composer

    cd ~
    php -r "readfile('https://getcomposer.org/installer');" > composer-setup.php
    php composer-setup.php
    sudo mv composer.phar /etc/php5/composer.phar
    sudo chmod +x /etc/php5/composer.phar
    sudo ln -s /etc/php5/composer.phar /usr/bin/composer
  • Install dependencies (vpn):

    cd /home/wwwroot/wwwroot
    composer install
  • Create Database and user, privileges:

    mysql -p -u root
     
    > create database yourdb;
    > create user 'you'@'localhost';
    > set password for you@localhost = PASSWORD('yourpasswd');
    > grant all privileges on yourdb.* to you@localhost;
    > show grants for you@localhost;
    > flush privileges;
  • reset config for environment

    cp .env.example .env
     
    vi .env
     
    DB_HOST=127.0.0.1
    DB_DATABASE=yourdb
    DB_USERNAME=yourame
    DB_PASSWORD=yourpasswd
  • Database migration

    php artisan key:generate
        Application key [s1ZYF0BZydwbRRcrNc58crIC20uwBRzT] set successfully.
    php artisan migrate
    php artisan db:seed
  • Install bower, gulp

    sudo npm install bower -g
    sudo npm install gulp -g
  • Bower install dependencies (no-VPN prefered)

    bower install
  • Generate css, js etc. frontend files

    gulp
     
    gulp watch
  • Make a directory for log files,

    sudo mkdir /home/wwwlogs
    sudo chown www-data.www-data /home/wwwlogs
    1. Reload Nginx

      sudo nginx -s reload

    Check the status:

        sudo service nginx status
    1. Restart Nginx

      sudo service nginx restart

    sudo mv yoursite.conf sites-available/

    C: char* conversion to LPCWSTR

    #include <string.h>
    #include <strlib.h>
    
    LPCWSTR c2ws(const char* s){
     int len;
     int slength = strlen(s)+1;
     len = MultiByteToWideChar(CP_ACP, 0, s, slength, 0, 0);
     wchar_t* buf = new wchar_t[len];
     MultiByteToWideChar(CP_ACP, 0, s, slength, buf, len);
     LPCWSTR r(buf);
     delete[] buf;
     return r;
    }
    

    Friday, May 20, 2016

    Install Pygame for Python 2.7 on Windows 64bit

    Check here for pygame wheel.

    My config goes like C:\WinPython-64bit-2.7.10.3\python-2.7.10.amd64, so it is a pre-compiled python bundle. The official site lists release only for 32-bit. But it gives the link to a wheel link.

    Basically, this is a personal managed wheel list. Choose the follow wheel and install through pip command

    pip install pygame-1.9.2a0-cp27-none-win_amd64.whl

    Refs

    Sunday, April 17, 2016

    Install Intel Dual Band Wireless-AC 3165 wireless driver on Ubuntu 15.04

    Check your wireless card shipped

    sudo update-pciids
    lspci
    

    I have,

    ...
    07:00.0 Network controller: Intel Corporation Intel Dual Band Wireless-AC 3165 Plus Bluetooth (rev 99)
    

    Copy firmware files

    Clone all intel firmwares from OpenELEC repository,

    git clone https://github.com/OpenELEC/iwlwifi-firmware
    cd iwlwifi-firmware/firmware
    sudo cp iwlwifi-7265*  /lib/firmware
    

    Installing Driver

    sudo apt-get install build-essential
    git clone https://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/backport-iwlwifi.git -b release/LinuxCore14
    cd backport-iwlwifi
    make defconfig-iwlwifi-public
    sed -i 's/CPTCFG_IWLMVM_VENDOR_CMDS=y/# CPTCFG_IWLMVM_VENDOR_CMDS is not set/' .config
    make -j4
    sudo make install
    

    It will output the following,

      Building modules, stage 2.
      MODPOST 6 modules
      INSTALL /home/jasler/backport-iwlwifi/compat/compat.ko
    Can't read private key
      INSTALL /home/jasler/backport-iwlwifi/drivers/net/wireless/iwlwifi/iwlwifi.ko
    Can't read private key
      INSTALL /home/jasler/backport-iwlwifi/drivers/net/wireless/iwlwifi/mvm/iwlmvm.ko
    Can't read private key
      INSTALL /home/jasler/backport-iwlwifi/drivers/net/wireless/iwlwifi/xvt/iwlxvt.ko
    Can't read private key
      INSTALL /home/jasler/backport-iwlwifi/net/mac80211/mac80211.ko
    Can't read private key
      INSTALL /home/jasler/backport-iwlwifi/net/wireless/cfg80211.ko
    Can't read private key
      DEPMOD  3.19.0-58-generic
    depmod will prefer updates/ over kernel/ -- OK!
    Note:
    You may or may not need to update your initramfs, you should if
    any of the modules installed are part of your initramfs. To add
    support for your distribution to do this automatically send a
    patch against "update-initramfs.sh". If your distribution does not
    require this send a patch with the '/usr/bin/lsb_release -i -s'
    ("Ubuntu") tag for your distribution to avoid this warning.
    
    Your backported driver modules should be installed now.
    Reboot.
    

    Links

    1. list of intel linux wireless drivers
    2. How can I install intel dual band wireless-ac 3165 drivers
    3. iwlwifi core release
    4. iwlwifi community

    Wednesday, February 17, 2016

    PyInstaller: Tweaking spec file

    Install PyInstaller

    pip install pyinstaller
    

    Generate spec file

    pyinstaller --onefile foo.py
    

    Tweak spec file

                 datas=[("myfile.txt", "."),
                        ("mydb.db", ".")
                 ],
                 hiddenimports=["packaging", "packaging.version", "packaging.specifiers"],
    

    In one-file mode, no COLLECT is called within spec file, so finally there will be only one exe file generated.

    Generate one-file exe

    pyinstaller foo.spec
    

    Saturday, December 26, 2015

    Python, OpenCV: Video Capture and Display

    OpenCV: Video Capture

    import time
    import cv2
    
    video_capture = cv2.VideoCapture(0)
    while True:
        t0=time.time()
        ret, frame = video_capture.read()
        t1=time.time()
        print "passed ", t1-t0, "s"
    
        cv2.imshow('Video', frame)
        #on pressing "q" exit
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break
            
    video_capture.release()
    cv2.destroyAllWindows()  
    

    Frames Per Second Counter

    #test how many frames per second for a webcam
    import time
    import cv2
    
    video_capture = cv2.VideoCapture(1)
    t0 = time.time()
    i=0
    while True:
        ret, frame = video_capture.read()
        print frame.shape
        t = time.time()
        if t-t0 > 1:
            t0=t
            print "frames ",i
            i=0
            
        i+=1    
                        
        cv2.imshow('Video', frame)
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break
            
    video_capture.release()
    cv2.destroyAllWindows()   
    

    Wednesday, December 23, 2015

    Python: JSON socket - Server/Client Structure

    JSON Socket Library

    #file:jsonsocket.py
    #https://github.com/mdebbar/jsonsocket
    import json, socket
    
    class Server(object):
      """
      A JSON socket server used to communicate with a JSON socket client. All the
      data is serialized in JSON. How to use it:
    
      server = Server(host, port)
      while True:
        server.accept()
        data = server.recv()
        # shortcut: data = server.accept().recv()
        server.send({'status': 'ok'})
      """
    
      backlog = 5
      client = None
    
      def __init__(self, host, port):
        self.socket = socket.socket()
        self.socket.bind((host, port))
        self.socket.listen(self.backlog)
    
      def __del__(self):
        self.close()
    
      def accept(self):
        # if a client is already connected, disconnect it
        if self.client:
          self.client.close()
        self.client, self.client_addr = self.socket.accept()
        return self
    
      def send(self, data):
        if not self.client:
          raise Exception('Cannot send data, no client is connected')
        _send(self.client, data)
        return self
    
      def recv(self):
        if not self.client:
          raise Exception('Cannot receive data, no client is connected')
        return _recv(self.client)
    
      def close(self):
        if self.client:
          self.client.close()
          self.client = None
        if self.socket:
          self.socket.close()
          self.socket = None
    
    
    class Client(object):
      """
      A JSON socket client used to communicate with a JSON socket server. All the
      data is serialized in JSON. How to use it:
    
      data = {
        'name': 'Patrick Jane',
        'age': 45,
        'children': ['Susie', 'Mike', 'Philip']
      }
      client = Client()
      client.connect(host, port)
      client.send(data)
      response = client.recv()
      # or in one line:
      response = Client().connect(host, port).send(data).recv()
      """
    
      socket = None
    
      def __del__(self):
        self.close()
    
      def connect(self, host, port):
        self.socket = socket.socket()
        self.socket.connect((host, port))
        return self
    
      def send(self, data):
        if not self.socket:
          raise Exception('You have to connect first before sending data')
        _send(self.socket, data)
        return self
    
      def recv(self):
        if not self.socket:
          raise Exception('You have to connect first before receiving data')
        return _recv(self.socket)
    
      def recv_and_close(self):
        data = self.recv()
        self.close()
        return data
    
      def close(self):
        if self.socket:
          self.socket.close()
          self.socket = None
    
    ## helper functions ##
    
    def _send(socket, data):
      try:
        serialized = json.dumps(data)
      except (TypeError, ValueError), e:
        raise Exception('You can only send JSON-serializable data')
      # send the length of the serialized data first
      socket.send('%d\n' % len(serialized))
      # send the serialized data
      socket.sendall(serialized)
    
    def _recv(socket):
      # read the length of the data, letter by letter until we reach EOL
      length_str = ''
      char = socket.recv(1)
      while char != '\n':
        length_str += char
        char = socket.recv(1)
      total = int(length_str)
      # use a memoryview to receive the data chunk by chunk efficiently
      view = memoryview(bytearray(total))
      next_offset = 0
      while total - next_offset > 0:
        recv_size = socket.recv_into(view[next_offset:], total - next_offset)
        next_offset += recv_size
      try:
        deserialized = json.loads(view.tobytes())
      except (TypeError, ValueError), e:
        raise Exception('Data received was not in JSON format')
      return deserialized
    

    Server

    #file:server.py
    from jsonsocket import Server
    
    host = 'LOCALHOST'
    port = 8080
    
    server = Server(host, port)
    
    while True:
        server.accept()
        data = server.recv()
        server.send({"response":data})
    
    server.close()
    

    Client

    #file:client.py
    from jsonsocket import Client
    import time
    
    host = 'LOCALHOST'
    port = 8080
    
    i=1
    while True:
        client = Client()
        client.connect(host, port).send({'test':i})
        i+=1
        response = client.recv()
        print response
        client.close()
        time.sleep(1)
    

    Tuesday, December 22, 2015

    Python: Pitfalls Filled

    # list to string, separated by comma
    lis = [1,2,3]
    print ",".join(map(str, lis))
    
    # print system time in formated way - logging time
    from time import gmtime, strftime
    strftime("%Y-%m-%d %H:%M:%S", gmtime())
    
    #appending dict or merging two dicts
    b={}
    d=b.copy()
    d.update({'list':0})
    
    #joining dict with string
    yook = {'a':0,'img':['url2','url2']}
    print str(yook) + "asd"
    
    #pretty print (json - dict)
    a= {u'response': {u'url': u'http://www.faceplusplus.com/static/img/demo/9.jpg', u'img_id': u'2081892e329727f350337509ff939a29', u'img_width': 540, u'session_id': u'd6fdce4b591e43dabbd8d31f68db0a46', u'face': [{u'attribute': {u'gender': {u'confidence': 99.7639, u'value': u'Male'}, u'age': {u'range': 9, u'value': 23}, u'race': {u'confidence': 99.9662, u'value': u'White'}, u'smiling': {u'value': 13.909}}, u'face_id': u'42dd2bdec1f8fae250a8d4c6b5f11837', u'tag': u'', u'position': {u'eye_left': {u'y': 44.727248, u'x': 58.625}, u'center': {u'y': 46.730245, u'x':59.537037}, u'width': 5.0, u'mouth_left': {u'y': 47.659401, u'x': 58.412037}, u'height': 7.356948, u'mouth_right': {u'y': 47.838692, u'x': 60.201481}, u'nose':{u'y': 46.782834, u'x': 59.463519}, u'eye_right': {u'y': 44.922616, u'x': 60.493333}}}], u'img_height': 367}}
    
    from pprint import pprint
    pprint(a)
    

    It is prettier, isn't it?

    {u'response': {u'face': [{u'attribute': {u'age': {u'range': 9,
                                                      u'value': 23},
                                             u'gender': {u'confidence': 99.7639,
                                                         u'value': u'Male'},
                                             u'race': {u'confidence': 99.9662,
                                                       u'value': u'White'},
                                             u'smiling': {u'value': 13.909}},
                              u'face_id': u'42dd2bdec1f8fae250a8d4c6b5f11837',
                              u'position': {u'center': {u'x': 59.537037,
                                                        u'y': 46.730245},
                                            u'eye_left': {u'x': 58.625,
                                                          u'y': 44.727248},
                                            u'eye_right': {u'x': 60.493333,
                                                           u'y': 44.922616},
                                            u'height': 7.356948,
                                            u'mouth_left': {u'x': 58.412037,
                                                            u'y': 47.659401},
                                            u'mouth_right': {u'x': 60.201481,
                                                             u'y': 47.838692},
                                            u'nose': {u'x': 59.463519,
                                                      u'y': 46.782834},
                                            u'width': 5.0},
                              u'tag': u''}],
                   u'img_height': 367,
                   u'img_id': u'2081892e329727f350337509ff939a29',
                   u'img_width': 540,
                   u'session_id': u'd6fdce4b591e43dabbd8d31f68db0a46',
                   u'url': u'http://www.faceplusplus.com/static/img/demo/9.jpg'}}
    
    

    Friday, December 18, 2015

    Windows DOS Batch: Rename all the folders numerically

    The following snippet renames all folders in current directory to numbers starting from 0.

    set i=0
    for %f in (*) do (set /A "i=i+1")
    

    References

    Thursday, December 17, 2015

    Python: Call Function From String

    Somehow there is a need to make calls from string, i.e. I have the name of the functions in string, now I need to call that function from that string.

    import inspect
    
    class API:
        def f1(self):
            print "f1 is called from",self.__class__.__name__
            
    def f1():
        print "f1 is called from",inspect.stack()[0][3]
            
    api = API()
    a = "f1"
    
    globals()[a]()
    getattr(api,a)()
    

    The results should be

    f1 is called from f1
    f1 is called from API
    

    Tuesday, December 1, 2015

    Windows cmd: Create Incrementing Folders With For Loop

    Bring up Windows console with Win+R and cmd, type

    for /l %i in (1,1,100);do mkdir %i
    

    Syntax

          FOR /L %%parameter IN (start,step,end) DO command 
    

    Notice that, double percentage symbol is used for batch file, and on the command line

    %%parameter : A replaceable parameter:
                     in a batch file use %%i (on the command line %i)
    

    References

    Tuesday, November 3, 2015

    HTML5 Image Capture on Mobile and Server-side Handling

    Since on mobile browsers, the video tag is not fully supported, one need to use the following to take a shot.

    <button onclick="$('#inputv').trigger('click');">Take a shot</button>
    <input type="file" id="inputv" name="inputv" accept="image/*" capture="camera" style="display:none">
    <div id="f_img"></div>
    

    And on js side, you need to utilize FileReader object to read the image shot from it. The image is stored in base64 string format, which can be added to src attribute to show the image on the page.

    window.addEventListener("DOMContentLoaded", function(){
        if (window.File && window.FileReader && window.FileList && window.Blob) {
            $("#inputv").change(function(e){
                    var f = e.target.files[0];
                    //  alert(f.size);
                    var reader = new FileReader();
                    reader.onload = function(e) {
                        //write your code to process the image
                        $("#f_img").html('<img src="' + e.target.result + '">');
                    };
                    reader.readAsDataURL(f);
            });
        // Great success! All the File APIs are supported.
        } else {
            $("#notice").append('The File APIs are not fully supported in this browser.');
        }
    

    The image in base64 can be uploaded to the server part using input tag with the type as text. A possible server-side handling witten in python can be the following:

    from flask import request
    
    image = request.form['image']
    
    def save_b64(image):
        img_str = str(image) #unicode to str obj
        head="data:image/jpeg;base64,"
        if str(img_str).startswith(head):
            l = len(head)
            img_str = img_str[l:]
        
        import time
        timestr = time.strftime("%Y%m%d%H%M%S")
        path = "image/capture-" + timestr + ".jpg"
        try:
            img = open(path, "wb")
            img.write(img_str.decode('base64'))
            img.close()
            return path
        except Exception as e:
            return False
    

    Monday, April 20, 2015

    OpenCV: Passing Parameters to Trackbar Callback Function

    OpenCV Trackbars are created through the system call like below, with a callback function which is called when there is any change on the bar.

    createTrackbar("Dummy Trackbar Name", "Dummy Window Name", &pos, max_pos, onTrackbarChange, &u);
    

    Here pos is the pass-by-ref variable that records the current position of trackbar, max_pos denotes its maximum possible value of this variable that the bar can handle. onTrackbarChange is the callback function u is the user data that is passed to the callback function.

    onTrackbarChange is prototyped as

    void onTrackbarChange(int, void*);
    

    Since there is only limited parameters, the data has to be packaged into an object or a structure like this,

    typedef struct {
     Mat* grad;
     Mat* dst;
     Mat* detected_edges;
     int* pos;
     int* ratio;
     int* kernel_size;
     char* window_name;
    } userdata;
    

    Of cource, the members within userdata structure could be whatever type you might need. Here I grab a snippet of what my demo is using. Thus you can implement the callback function on demand.

    void onTrackbarChange(int pos, void* ud) {
     userdata u = *static_cast(ud);
    
     // Reduce noise with a kernel 3x3
     blur(*u.grad, *u.detected_edges, Size(3, 3));
    
     // Canny detector
     Canny(*u.detected_edges, *u.detected_edges, *u.pos, *u.pos*(*u.ratio), *u.kernel_size);
    
     // Using Canny's output as a mask, we display our result
     *u.dst = Scalar::all(0);
    
     (*u.grad).copyTo(*u.dst, *u.detected_edges);
     imshow(u.window_name, *u.dst);
            waitKey(0);
    }
    

    Friday, April 11, 2014

    CentOS: Compiling and Installing PHP Imagick extension

    Requirements

    This extension requires ImageMagick version 6.2.4+ and PHP 5.1.3+. Package information is here, Imagick package on PECL

    The normal procedure goes like this

        wget http://pear.php.net/go-pear.phar
        php go-pear.phar
        pecl install imagick
    

    While it throws the following error,

        No releases available for package "pecl.php.net/imagick"
        install failed
    

    So I decided to compile directly from source (in order to generate imagick.so)

        yum install php-pear php-devel
        yum install ImageMagick ImageMagick-devel
        yum install pcre-devel
        wget http://pecl.php.net/get/imagick-3.2.0RC1.tgz
        tar -xvf imagick-3.2.0RC1.tgz
        cd imagick-3.2.0RC1/
        phpize
        ./configure
        make
        make test
        make install
    

    Remember to turn on the extension in the php configuration file.

        vim /etc/php.ini
            extension = imagick.so
    

    References

    Sunday, April 6, 2014

    PHP: Get Token From Dropbox

    Just use Dropbox for serving the files/pictures of your personal site or startup site, for free use, there is up to 16 GB maximum capacity, far enough to carry out your idea.

    First off, we will sign up for Dropbox, start a application that uses Core API. This will give you the key and secret. Prepare it in a file named config.json.

    {
      "key": "your-dropbox-api-key",
      "secret": "your-dropbox-api-secret"
    }
    

    Download you PHP sdks from here: https://www.dropbox.com/developers/core/sdks/php. Unzip and put in your project directory.

    Prepare you getdbxtoken.php as following, this will load dropbox php library along with you config in the previous json file.

    <?php
    require_once "dropbox-php-sdk-1.1.3/lib/Dropbox/autoload.php";
    use \Dropbox as dbx;
    
            $appInfo = dbx\AppInfo::loadFromJsonFile("config.json");
            $webAuth = new dbx\WebAuthNoRedirect($appInfo, "PHP-Example/1.0");
            $authorizeUrl = $webAuth->start();
            echo "1. Go to: " . $authorizeUrl . "\n";
            echo "2. Click \"Allow\" (you might have to log in first).\n";
            echo "3. Copy the authorization code.\n";
            $authCode = \trim(\readline("Enter the authorization code here: "));
    
            list($accessToken, $dropboxUserId) = $webAuth->finish($authCode);
            print "Access Token: " . $accessToken . "\n";
    
            $dbxClient = new dbx\Client($accessToken, "PHP-Example/1.0");
            $accountInfo = $dbxClient->getAccountInfo();
            print_r($accountInfo);
    
    ?>
    

    Run the script from command line:

    chmod a+x getdbxtoken.php
    php -q getdbxtoken.php
    

    You will need to input auth code in order to get the token, which is obtained by following the link and give the allow permission (go to the brower and [login in] and grant that). While you get that auth code, copy it to your command line, press enter. It will throw you the access token. In consequence, we tried to open a new client and fetch the account info, which is returned as an array, printed to your screen later.

    1. Go to: https://www.dropbox.com/1/oauth2/authorize?locale=&client_id=SOME_CLIEND_ID&response_type=code
    2. Click "Allow" (you might have to log in first).
    3. Copy the authorization code.
    Enter the authorization code here: 
    

    To note once obtained the token, you might want to save it to a secure place since you don't need to log in (auth) again. Next time you can just build client by the token, and connect directly to dropbox.

    Sunday, March 23, 2014

    Ubuntu: Compile Hylafax 6.0.6 From Source

    Let's do it all in the terminal.

    wget ftp://ftp.hylafax.org/source/hylafax-6.0.6.tar.gz
    tar -xvf hylafax-6.0.6.tar.gz
    cd hylafax-6.0.6/
    sudo apt-get install g++
    sudo apt-get install libtiff4 libtiff4-dev libtiff-tools
    ./configure
    make
    sudo make install
    

    Note at the configuration stage, some confirmations will pop out, such as

    HylaFAX configuration parameters (part 1 of 2) are:
    
    [ 1] Directory for applications:        /usr/local/bin
    [ 2] Directory for lib data files:      /usr/local/lib/fax
    [ 3] Directory for lib executables:     /usr/local/sbin
    [ 4] Directory for system apps:   /usr/local/sbin
    [ 5] Directory for manual pages:        /usr/local/man
    [ 7] Directory for spooling:            /var/spool/hylafax
    [ 8] Directory for uucp lock files:     /var/lock
    [ 9] Uucp lock file scheme:             ascii
    [10] PostScript imager package:         gs
    [11] PostScript imager program:         /usr/bin/gs
    [12] Manual page installation scheme:   bsd-source-cat
    [13] Default page size:                 North American Letter
    [14] Default vertical res (lpi):        98
    
    HylaFAX configuration parameters (part 2 of 2) are:
    
    [15] Location of getty program:         /sbin/agetty
    [16] Location of voice getty program:   /bin/vgetty
    [17] Location of sendmail program:      /usr/lib/sendmail
    [18] Location of TIFF tools:            /usr/bin
    [19] Location of SysV init scripts: /etc/init.d
    [20] Location of SysV start scripts: ../rc2.d ../rc3.d ../rc4.d ../rc5.d
    [21] Location of SysV stop scripts: ../rc0.d ../rc1.d ../rc6.d
    [22] Name of SysV start script:  S97hylafax
    [23] Name of SysV stop script:  K05hylafax
    [24] Init script starts faxq:  yes
    [25] Init script starts hfaxd  yes
    [26] Start paging protocol:  no