Jan 4, 2014

Lập trình file zip

Đầu năm tính viết cái gì đó hoành tá tràng, nhưng lại bận quá nên thôi. Lại tính đổi cái theme, quả thực trình design kém đi rinh đồ người khác đôi lúc hơi mệt.

Nhắc mới nhớ, tranh thử mấy ngày Tết về viết hoàn thành những bài còn dang dở :).

Nov 14, 2013

Khôi phục USB Transend

Vừa bị chê cái giao diện của blog xấu, chăc hôm nào rảnh lại đi tìm theme khác vậy.

Quay lại chủ đề của entry này. Lâu nay mình vẫn trung thành với USB của Transcend. Ngày xưa thì xài cái USB 256MB, qua nhiều đợt mất, hư, cho mượn nhưng dân tình không trả, mình vẫn xài các thế hệ tiếp theo của em ý.

Chẳng là hôm trước cần cài lại Windows 8, và cũng phải config lại Boot Menu của Linux (khi cài Windows xong thì boot menu của GRUB 2 cũng mất theo). Sau một hồi nghịch, forrmat các kiểu thì Windows không còn nhận ra USB nữa. Kích thước ổ đĩa quay về mức 0 byte. Lúc đó đã cố gắng tìm một số tool chuyên dụng để forrmat lại cũng không thành công, trước đó thì usb mình không còn khả năng boot được nữa. Trong lúc không biết làm gì, mình quoẻn quởn lên trang của TRanscend và download tool của nó về. Và thật kỳ diệu, nó đã fix được cái USB xấu số một dăm ba cái Next.
Link download
Không biết các hãng khác có tool này không, nhưng tool này thực sự hữu dụng và cực kỳ dễ dùng.

Oct 6, 2013

Bộ lọc tuyến tính.

Đáng lí ra sẽ có bài về các phép tính trên từng pixel, nhưng vì hiện giờ đang học về filter. Nên sẽ nói về filter trước.

Bài viết dưới đây được lấy và tham khảm từ một số nguồn:

  • Khóa Computer Vision - Stanford.
  • Cuốn "Computer Vision - A Modern Approach".
  • Một số nguồn linh tinh khác sẽ được liệt kê sau.

Một ảnh thực chất là biểu diễn của một hàm từ không gian $R^2$ sang không gian $R^M$. Hàm này sẽ cho ta biết về cường độ của điểm ảnh tại vị trí (x, y). Chính vì vậy, khi $M=1$ ta được ảnh mức xám, khi $M=3$ ta sẽ được ảnh màu gồm 3 kênh. Tuy nhiên, vì một ảnh trong tự nhiên là một hàm có tập xác định là tập số thực, nhưng máy tính chỉ hiểu được ảnh ở miền là các số nguyên. Vì vậy ta cần một bước để chuyển ảnh từ không gian thực sang miền mà máy tính hiểu được. Phép biến đổi đó gọi là số hóa.

Số hóa bao gồm các 2 phép chính:

  1. Sampling.
  2. Quantization - lượng hóa.

Phép Sampling làm nhiệm vụ chuyển tập xác định từ số thực sang số nguyên. Đơn giản hơn, sampling là phép dùng 1 cái lưới rộng và trùm lên trên tấm ảnh. Mỗi ô của lưới được gọi là pixel.

Sau khi thực hiện xong Sampling, ta sẽ chỉ chọn đúng 1 màu duy nhất cho mỗi pixel của ảnh. Giá trị này là số nguyên. Việc chọn giá trị của pixel như thế nào, hay chia lưới như thế nào là một kỹ thuật riêng, và ... khá là hấp dẫn. Sẽ được bàn luận sau vậy.

Bộ lọc tuyến tính - Linear Filters

Một bộ lọc có chức năng chuyển một tấm ảnh thành một tấm ảnh mới, mà những pixel của ảnh mới là tổ hợp giá trị pixel của các ảnh cũ. Việc dùng các bộ lọc có tác dụng:

  • Rút trích những thông tin hữu ích từ ảnh.
  • Thay đổi hoặc tăng cường các thuộc tính của ảnh.

Để sử dụng filter, ta áp dụng công thức sau:

\[ g(x,y) = \sum_{k,l}f(i-k, j-l)h(k,l) \]

Trong đó $g(x,y)$ là ảnh kết quả. $f(x,y)$ là ảnh đầu vào, $h(k,l)$ là mặt nạ (mask) hay còn gọi là nhân (kernel).

Công thức phía trên có thể viết gọn thành:

\[ g = f \bigotimes g \]

Tham khảo:

  • Computer Vision - A Modern Approach
Còn tiếp.

Sep 21, 2013

Bật chế độ God Mode trong Windows 7/8

Đây là một trong những tính năng ẩn của Windows. Sau 1 ngày vật vã để sửa lại driver Windows 8, mình tình cờ phát hiện ra em này.

Chức năng: Liệt kê tất cả các chức năng cho phép và hợp pháp để chỉnh sửa, cấu hình trong Windows 7/8.
Thực hiện:
  1. Ra ngoài Desktop và tạo 1 thư mục
  2. Đối với Windows 7. Nhập tên thư mục như sau:
    GodMode.{ED7BA470-8E54-465E-825C-99712043E01C}
    Đối với Windows 8:
    GodMode.{ED7BA470-8E54-465E-825C-99712043E01C}
    Gõ xong phát hiện 2 cái này giống nhau :)). Kết quả sau đó ta được một thư mục liệt kê như sau:

Sep 19, 2013

Driver Wifi trên Windows 8

Vụ này không share không được, kể từ khi cài Windows 8 lên trên em Dell dòng Inspiron thì có hiện tượng mạng cực kỳ chậm và dễ gây ức chế kinh khủng. Đã vậy còn chập chờn.

Giải pháp là đây: Link download . Trong hàng tá cách, thì đây là cách đơn giản nhất, và là giải pháp hữu hiệu nhất. Xóa Driver cũ của Windows đi và cài cái mới này.
Chi tiết từng bước:
  1. Vào Control Panel - > Device Manager. Ta Click chuột phải vào Broadcom 802.11n rồi chọn Disable
  2. Sau đó chọn tiếp Uninstall
  3. sau khi xóa xong, Windows sẽ cố gắng tìm driver trong hệ thống để cài lại, và nếu nó cài thành công thì mọi chuyện vẫn hoàn cũ. Lúc này nhanh chóng cài driver mới tải kia về. Vậy là mọi chuyện được ổn thỏa.
  4. Trường hợp không tắt được dịch vụ tự tìm driver: ta click vào Properties của driver đó, chọn thẻ Driver chọn button Driver Details Trong đó liệt kê tất cả các file liên quan đến driver. Ta chỉ cần vào từng file rồi xóa. Sau đó cài lại driver mới.

Sep 5, 2013

Load ảnh từ OpenCV

Chào mừng năm học mới, thắng lợi mới nên mình sẽ viết một loạt series về opencv và một số kiến thức liên quan đến thị giác máy tính. Một phần để phục vụ việc học tập( ngâm cứu) của bản thân, một phần chia sẻ kiến thức với bạn nào có đam mê và muốn thử với lĩnh vực này.

Chủ đề của hôm nay. Mở đầu năm học bằng 1 công việc rất đơn giản: load ảnh dùng opencv.
Ngôn ngữ:C++, sẽ bàn một chút đến C và Python.
Để load 1 ảnh đã tồn tại trong bộ nhớ ngoài, ta dùng API imread.
Tham số của API này:
  • filename (const char*): đường dẫn đến file cần load.
  • flags (int): các tùy chọn khi load ảnh. Một số tham số hay ho:
    • &gt 0: Trả lại ảnh có 3 kênh màu. Kênh $ \alpha $ sẽ bị lược bỏ.
    • = 0: Trả về ảnh mức xám.
    • &lt 0: Trả về ảnh nguyên gốc.
imread sẽ trả lại là một đối tượng kiểu Mat. Nếu không thành công, kết quả trả về sẽ là một ma trận rỗng, tức Mat::data = NULL. Ta có thể dùng kết quả này để check xem file thực sự đã được load hay chưa. Bởi vì imread không có cơ chế exeptions nên khi có lỗi xảy ra, ta phải đợi đến các hàm xử lý tiếp theo (có exceptions hoặc assert) mới biết được. Điều này rất là bất lợi khi debug: ta cứ nghĩ ảnh đã được load vào, nhưng thực sự là chưa.
Sau khi load xong, công việc tiếp theo sẽ là show tấm ảnh đó ra màn hình. OpenCV hỗ trợ tốt tác vụ này với API: imshow. Tham số lần lượt của API này như sau:
  1. windows name (string): Tên của cửa sổ màn hình.
  2. image (Mat): biến lưu trữ ảnh đã được load
Đoạn mã ví dụ:

1
2
3
4
5
6
7
8
9
#include <opencv2\opencv.hpp>
using namespace cv;
int main()
{
    Mat img = imread("hello.png", 1);
    imshow("show image", img);
    waitKey(0);
    return 0;
}

Hàm waitKey có một chức năng nho nhỏ. Nó sẽ đợi người dùng nhấn một phím bất kỳ rồi mới thực hiện công việc tiếp theo. Tham số đầu vào là 0, mặc định là vậy. Lớn hơn 0 là số milisecond mà waitKey sẽ delay.
Tất cả các api vừa kể trên là của C++, OpenCV hỗ trợ cả ngôn ngữ C. Để tránh nhầm lẫn đáng tiếc( vì C/C++ là hai anh em rất là gần gũi nhau), nên các API kể trên đều nằm trong namespace cv. Còn các cấu trúc khác thuộc C sẽ có tiền tố CV đứng trước.
Vậy ứng dụng của đoạn code nho nhỏ này là gì? Một điều hay ho của các API bên OpenCV là nó cross-platform. Rinh qua bên Linux chạy ngon, và để Windows cũng tốt chán. Vì cái sự cross-platform đó, và vì đây là thư viện tập trung vào xử lý ảnh, nên số các API hỗ trợ user interface rất ít. Nhưng, nhưng ít ra, nó cũng đủ cho ta chế 1 tool graphic debug. :D
Ý tưởng:
  • Một cửa sổ Windows cho phép resize, đồng thời là 1 điểm breakpoint kiểm tra xem đoạn code của ta tới đó đã thỏa mãn chưa.
  • (Option): Click vào mỗi pixel sẽ trả về giá trị ở pixel đó.
Hướng giải quyết:
  • Việc tạo 1 của sổ cho phép resize ảnh không khó, việc tạo breakpoint đơn thuần là gọi hàm waitKey().
  • Việc đọc giá trị của pixel phụ thuộc rất lớn vào: số kênh của ảnh (1, 3), và kiểu lưu trữ của mỗi kênh đó (uchar, float, double, int)... Việc click để chọn vị trí pixel khá đơn giản. Tuy nhiên, hiện nay mình vẫn chưa có cách thỏa đáng nào (ngoại trừ việc if...else một đống các trường hợp và gọi từng hàm phù hợp.
Tạo một header file. ví dụ là debugtool.h có nội dung sau:
1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
#ifndef __DEBUGTOOL
#define __DEBUGTOOL

#include <cassert>
#include <opencv2/opencv.hpp>
void __clickevent(int evnt, int x, int y, int flags, void* params);
#ifdef NDEBUG
#define debug_img(img) 
#else
#define debug_img(img) {\
 cv::namedWindow("Debug:"#img, CV_WINDOW_NORMAL | CV_WINDOW_FREERATIO);\
 cv::setMouseCallback("Debug:"#img, __clickevent,(void*) &img);\
 cv::imshow("Debug:"#img, img);\
    cv::waitKey(0);\
 cv::destroyWindow("Debug:"#img);\
 }
#endif

#endif
Sau đó tạo file cpp tên debugtool.cpp có nội dung:
1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
#include "debugtool.h"

void __clickevent(int event, int x, int y, int flags, void* params)
{
    if (event != CV_EVENT_LBUTTONUP) return;
    IplImage *iplImg = new IplImage(*(cv::Mat*) params);   
    assert(iplImg->imageData != NULL);
    std::cout << "(" << x << "," << y << "): " 
                << cv::Scalar(cvGet2D(iplImg ,x, y)) << std::endl;
    std::cout.flush();
}

Xong, giờ có thể dùng debug_img bất cứ đâu như 1 breakpoint kiểm tra 1 ảnh. Click vào pixe để xem các giá trị. :)

Aug 31, 2013

Nguyên tắc lập trình C/C++

Một số nguyên tắc lập trình trên C/C++ khá là hay, việc tuẩn thủ, hoặc làm theo những gợi ý được đề ra sẽ giúp lập trình viên tránh được một số "tính năng bất ngờ" mà C++ gây ra mà ta không lường trước được. Đồng thời giúp lập trình viên có thói quen làm việc hiệu quả hơn


  • Original Indian Hill guide with annotations by H. Spencer. PDF
  • Indian Hill C style guide, as amended at UofT, UW, and elsewhere. PDF
  • C++ coding rules from Ellemtel (Swedish Telecom) by Mats Henricson and Erik Nyquist. PDF
  • C++ style guide from Wildfire Communications. Link
  • C++ Coding Standard by Todd Hoff. Link.
  • C++ style advice called "The Tao of Coding" from Koen Witters.Link
  • The C Style Guide and Programming Guidelines from The C Kernel pages by Peter van der Vlugt.PDF
  • Words of wisdom from Henry Spencer and Geoff Collyer about the appropriate use of #ifdefs, a paper presented at the Summer 1992 Usenix conference.PDF
  • C Coding Standard.Link

Aug 25, 2013

Ép kiểu ngầm định - Implicit conversion

Một buổi chiều dẹp các chuyện linh tinh bên Windows Phone, mình lại có hứng thú viết về cu C++ dấu yêu. Lần này là 1 chủ đề rất là nhỏ: ép kiểu ngầm định (implicit conversion)

Vì sao gọi là nhỏ? Vì nó khá là cổ điển và ít được quan tâm nhiều lắm. Tuy nhiên để tìm hiểu tận gốc vấn đề thì cái này khá là hay ho.

Ép kiểu ngầm định từ T1 sang T2 xảy ra khi trong một biểu thức kiểu T1 được dùng trong ngữ cảnh nó không được chấp nhận, tuy nhiên, ngữ cảnh đó lại chấp nhận kiểu T2.

Ví dụ:

int b = 1.2 + 3.4;

Biểu thức ở đây có kiểu là float, nhưng ngữ cảnh của nó sử dụng lại là kiểu

int
. Và thế là chương trình phải làm một cái gì đó để chuyển đổi giữa kiểu float sang int, tuy nhiên điều này không được người lập trình đề cập, thành ra trình biên dịch sẽ tự làm âm thầm và đó chính là ép kiểu ngầm định .

Đọc cái này. Và ta cần highlight một số đoạn sau.

Standard conversions affect fundamental data types

Điều gì ở đây? Standard conversion và fundamental data types .Các kiểu dữ liệu cơ sở đã cung cấp sẵn một số ép kiểu, người lập trình không cần định nghĩa lại. Đồng thời, những phương thức ép kiểu đó đã được nâng lên thành chuẩn. Danh sách các phép ép kiểu chuẩn hóa có trong đây (tài liệu từ MSDN ).

the compiler can signal with a warning. This warning can be avoided with an explicit conversion.

Về cái sự ép kiểu ngầm định có thể xảy ra mất mát thông tin (thử ép biến i = 1000 sang char thì biết), compiler sẽ thông báo với ta về sự mất mát thông tin đó. Tuy nhiên, nếu sử dụng ép kiểu chỉ định (explicit conversion) thì điều này không xảy ra. Lý do? Vì khi đó người lập trình đã chấp nhận mất mát thông tin, bởi chính họ là người đã gõ dòng code đó vào.

Tip nho nhỏ: để bật chế độ kiểu tra ép kiểu ngầm định, dùng option -Wconversion , option -Wall không support chuyện này.

Ép kiểu ngầm định xảy ra khi từ T1 sang T2 khi:

  1. Một biểu thức là tham số đầu vào có kết quả trả về là T1 nhưng tham số lại yêu cầu kiểu T2
  2. Một biểu thức có toán hạng là kiểu T2.
  3. Khởi gán một biến có kiểu T2.
  4. Lệnh return trả về kiểu T2.
  5. Biểu thức dùng trong lệnh switch (với T2 là integral type)
  6. Biểu thức dùng trong các lệnh if và các lệnh lặp. T2 trong trường hợp này là kiểu bool

Đọc tiếp tài liệu bên cpp, ta highlight tiếp phần này:

Implicit conversions also include constructor or operator conversions

Ép kiểu ngầm định cho phép dùng contructor và toán tử ép kiểu để chuyển đổi. Vậy ngoài standard conversions ra, ta còn có cả user-defined conversions. Vì vậy, compiler sẽ có một số nguyên tắc nhằm chọn ra phép biến đổi nào cần dùng:

  • Khi T2 là tham số của constructor hay của hàm chuyển kiểu do người dùng định nghĩa (user-defined conversion function) thì compiler sẽ ưu tiên cho standard conversion
  • Khi T2 và T1 đều là built-in types thì compiler sẽ ưu tiên standard conversions.

Tham khảo:

  1. Implicit cast in cppreference
  2. cplusplus
  3. MSDN