You are on page 1of 57

Binary- Image Processing

Robotic & Vision Lab RoVis


Content

• Threshold
• Histogram
• Pixel manipulation

Robotic & Vision Lab RoVis


Digital Image

Robotic & Vision Lab RoVis


RGB Image

KHÔNG GIAN MÀU SẮC


• Không gian màu RGB
RGB là không gian màu rất phổ biến được dùng trong đồ họa máy tính và nhiều thiết bị kĩ thuật số khác. Ý
tưởng chính của không gian màu này là sự kết hợp của 3 màu sắc cơ bản : màu đỏ (R, Red), xanh lục (G,
Green) và xanh lơ (B, Blue) để mô tả tất cả các màu sắc khác.

Robotic & Vision Lab RoVis


RGB Image

Nếu như một ảnh số được mã hóa bằng 24bit, nghĩa là 8bit cho kênh R, 8bit cho kênh
G, 8bit cho kênh B, thì mỗi kênh màu này sẽ nhận giá trị từ 0-255. Với mỗi giá trị khác
nhau của các kênh màu kết hợp với nhau ta sẽ được một màu khác nhau, như vậy ta
sẽ có tổng cộng 255x255x255 = 1.66 triệu màu sắc.

Robotic & Vision Lab RoVis


Images and pixels

• The value of each pixel is a single sample representing only an amount


of light, that is, it carries only intensity information.
• Varying from black at the weakest intensity to white at the strongest.
Often, the grayscale intensity is stored as an 8-bit integer giving 256
possible different shades of gray from black to white.
Robotic & Vision Lab RoVis
The intensity function

Robotic & Vision Lab RoVis


Ảnh xám : là ảnh có hai màu đen, trắng với mức xám hay cường độ sáng ở các điểm ảnh là khác nhau.
Giá trị xám thay đổi từ độ sáng yếu nhất là 0 đến độ sáng mạnh nhất là 255 Ví dụ
• Ảnh nhị phân: ảnh chỉ có 2 mức đen trắng. giá trị xám mức 0 tương đương với mức trắng và 255 (mức 1)
tương đượng với mức đen. Nói cách khác: mỗi điểm ảnh của ảnh nhị phân chỉ có thể là 0 hoặc 1.

Robotic & Vision Lab RoVis


Truy cập giá trị của pixel sử dụng thư viện Opencv
Để truy cập giá trị tọa độ của pixel và cường độ ảnh tại tọa độ đó ta lần lượt làm như
sau
1. Đọc ảnh màu
2. Chuyển sang ảnh xám
3. Định nghĩa một vector :
a. Scalar intensity1: cho ảnh xám
b. Vec3b intensity2: cho ảnh màu

Robotic & Vision Lab RoVis


Opencv access pixel

Robotic & Vision Lab RoVis


Mat M(2,2, CV_8UC3, Scalar(0,0,255)); cout << "M = " << endl << " " << M << endl << endl;

Mat C = (Mat_<double>(3,3) << 0, -1, 0, -1, 5, -1, 0, -1, 0); cout << "C = " << endl << " " << C << endl << endl;

Robotic & Vision Lab RoVis


1. Đọc giá trị ảnh xám của hình tại tọa độ (2,5)
2. Đọc giá trị R, G, B tại tọa độ (10,15) của ảnh màu
3. Chỉnh sửa ảnh màu như sau: từ hàng 100 và cột 100 quét đến hết hình đặt tăng cường độ đỏ 10,
tăng cường độ xanh dương 10, tăng cường độ xanh lá cây là 10
4. Chỉnh sửa ảnh xám như sau: tăng cường độ sáng ảnh lên 100.

Robotic & Vision Lab RoVis


#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "iostream"
using namespace cv;
using namespace std;
int main()
{
Mat src1;
src1 = imread("lena.png", CV_LOAD_IMAGE_COLOR);
namedWindow("Original image", CV_WINDOW_AUTOSIZE);
imshow("Original image", src1);
Mat gray;
cvtColor(src1, gray, CV_BGR2GRAY);
namedWindow("Gray image", CV_WINDOW_AUTOSIZE);
imshow("Gray image", gray);
// know the number of channels the image has
cout << "original image channels: " << src1.channels() << "gray image channels: " << gray.channels() << endl;

// ******************* READ the Pixel intensity *********************


// single channel grey scale image (type 8UC1) and pixel coordinates x=5 and y=2
// by convention, {row number = y} and {column number = x}
// intensity.val[0] contains a value from 0 to 255
Scalar intensity1 = gray.at<uchar>(2, 5);
cout << "Intensity gray at (2,5) = " << endl << " " << intensity1.val[0] << endl << endl;
// 3 channel image with BGR color (type 8UC3)
// the values can be stored in "int" or in "uchar". Here int is used.
Vec3b intensity2 = src1.at<Vec3b>(10, 15);

Robotic & Vision Lab RoVis


int blue = intensity2.val[0];
int green = intensity2.val[1];
int red = intensity2.val[2];
cout << "Intensity at (10,15) = " << endl << "blue= " << blue << "green= " << green << "red= " << red << endl
<< endl;

// ******************* WRITE to Pixel intensity **********************


// This is an example in OpenCV 2.4.6.0 documentation
for (int i = 0; i < gray.rows; i++)
{
for (int j = 0; j < gray.cols; j++)
{
gray.at<uchar>(j, i)= gray.at<uchar>(j, i)+100;
}
}
namedWindow("Gray image modify", CV_WINDOW_AUTOSIZE);
imshow("Gray image modify", gray);
// Modify the pixels of the BGR image
for (int i = 100; i < src1.rows; i++)
{
for (int j = 100; j < src1.cols; j++)
{
src1.at<Vec3b>(i, j)[0] = src1.at<Vec3b>(i, j)[0]+10;
src1.at<Vec3b>(i, j)[1] = src1.at<Vec3b>(i, j)[1] + 10;
src1.at<Vec3b>(i, j)[2] = src1.at<Vec3b>(i, j)[2] + 10;
}
}
namedWindow("Modify RGB pixel", CV_WINDOW_AUTOSIZE);
imshow("Modify RGB pixel", src1);
waitKey(0);

Robotic & Vision Lab RoVis


return 0;
}
Robotic & Vision Lab RoVis
Bài Tập: a) load 2 hình và tính khoảng cách Euclide giữa 2 màu (R,G,B)
b) Set threshold để thấy cánh tay

Robotic & Vision Lab RoVis


cv::Mat diffImage;
cv::absdiff(backgroundImage, currentImage, diffImage);

cv::Mat foregroundMask = cv::Mat::zeros(diffImage.rows, diffImage.cols, CV_8UC1);

float threshold = 30.0f;


float dist;

for(int j=0; j<diffImage.rows; ++j)


for(int i=0; i<diffImage.cols; ++i)
{
cv::Vec3b pix = diffImage.at<cv::Vec3b>(j,i);

dist = (pix[0]*pix[0] + pix[1]*pix[1] + pix[2]*pix[2]);


dist = sqrt(dist);

if(dist>threshold)
{
foregroundMask.at<unsigned char>(j,i) = 255;
}
}
Robotic & Vision Lab RoVis
Ví dụ 2.2: a) Đọc giá trị RGB tại điểm nhấn chuột phải (vùng mắt) của hình sau
b) Lưu lại 4 giá trị nhấn chuột đó

int main(int argc, char** argv)


{
#include "opencv2/highgui/highgui.hpp" // Read image from file
#include <iostream> Mat img = imread("Machovka_Happy_fish.PNG");
using namespace std; //if fail to read the image
using namespace cv; if (img.empty())
void mouseEvent(int evt, int x, int y, int flags, void* param) {
{ cout << "Error loading the image" << endl;
Mat* rgb = (Mat*)param; return -1;
if (evt == CV_EVENT_LBUTTONDOWN) }
{ //Create a window
printf("%d %d: %d, %d, %d\n", namedWindow("My Window", 1);
x, y, //set the callback function for any mouse event
(int)(*rgb).at<Vec3b>(y, x)[0], setMouseCallback("My Window", mouseEvent, &img);
(int)(*rgb).at<Vec3b>(y, x)[1], //show the image
(int)(*rgb).at<Vec3b>(y, x)[2]); imshow("My Window", img);
} // Wait until user press some key
} waitKey(0);
return 0;
}

Robotic & Vision Lab RoVis


Histogram
- Biểu đồ Histogram của một bức ảnh là biểu đồ biểu diễn sự phân bố của các mức
cường độ xám của một bức ảnh.
- Biểu đồ có 2 chiều với trục X là các giá trị màu của ảnh, trục Y là tổng số pixel. Với
ảnh có 8 bit màu mỗi kênh thì trục X có 256 cột giá trị từ 0 – 255. Từ trái qua phải là
bit có cường độ sáng thấp nhất là màu đen đến số lượng pixel có cường độ sáng
sáng nhất là màu trắng

Robotic & Vision Lab RoVis


dark light
pixels pixels

Robotic & Vision Lab RoVis


Histogram of an image

Robotic & Vision Lab RoVis


Ví dụ 2.3: một ảnh 4x4 có cường độ sáng như sau, tính histogram của hình

0 1 2 3
0 2 0 0 
Như vậy: cường độ 0 có 4 pixel 
cường độ 1 có 2 pixel 2 4 5 3
 
cường độ 2 có 2 pixel
1 5 5 4
cường độ 3 có 2 pixel

cường độ 4 có 2 pixel

cường độ 5 có 3 pixel

Histogram của ảnh là:

Hình 2.11 phân bố histogram của ví dụ 2.3

Robotic & Vision Lab RoVis


Trong Opencv có các hàm sau để sử dụng đọc histogram:

+ void calcHist(const Mat* images, int nimages, const int* channels, InputArray mask, OutputArray hist, int dims, const int*
histSize, const float** ranges, bool uniform=true, bool accumulate=false )

+ void normalize(InputArray src, OutputArray dst, double alpha=1, double beta=0, int norm_type=NORM_L2, int dtype=-1,
InputArray mask=noArray() )

Robotic & Vision Lab RoVis


Histogram equalization
- Phương pháp này được sử dụng nhằm làm tăng cường độ tương phản toàn cục
(global contrast) của bức ảnh, nó đặc biệt có ý nghĩa trong tình huống dữ liệu đầu vào
có giá trị điểm ảnh co cụm, độ tách bạch hình ảnh thấp (close contrast value). Điều này
có thể được nhận thấy rỏ thông qua thể hiện của biểu đồ histogram.
- Tuy nhiên nó lại có một khuyết điểm rất quan trọng, đó là nó dễ dàng làm tăng độ
tương phản của nhiễu trong nền của ảnh và giảm các chi tiết hữu ích trong ảnh.

Robotic & Vision Lab RoVis


Robotic & Vision Lab RoVis
Histogram equalization

Robotic & Vision Lab RoVis


Các bước cân bằng:
Bước 1: đếm số lượng pixel tương ứng của các mức xám
Bước 2: Tính toán khả năng phân bố của các pixel trong hình
Bước 3: Tính tổng tích lũy các khả năng này
Bước 4: Trải đều số lượng pixel trong hình
Ví dụ 2.5: Hãy cân bằng histogram của hình sau với mức xám từ 0->7

Robotic & Vision Lab RoVis


Đối với ảnh là ảnh xám, việc cân bằng histogram là đơn giản, ta chỉ cần gọi hàm
cvEqualizeHist(src, dst), trong đó src là ảnh xám nguồn và dst là ảnh xám đích có cùng
kích thước.
+ Tuy nhiên đối với trường hợp ảnh là ảnh màu, đầu tiên ta phải chuyển đổi sang không
gian màu hsv, sau đó cân bằng mức xám ở kênh màu V (value, tức là kênh về giá trị
cường độ sáng), cuối cùng là hợp các kênh này lại dùng hàm cvMerge để được kết quả
cuối cùng
Ví dụ: Hãy cân bằng histogram của ảnh sau
a) Sử dụng ảnh xám
b) Sử dụng ảnh RGB

Robotic & Vision Lab RoVis


//change the color image to grayscale image
cvtColor(image, image, COLOR_BGR2GRAY);
#include <opencv2/opencv.hpp>
#include <iostream> //equalize the histogram
Mat hist_equalized_image;
using namespace cv; equalizeHist(image, hist_equalized_image);
using namespace std;
//Define names of windows
int main(int argc, char** argv) String windowNameOfOriginalImage = "Original Image";
{ String windowNameOfHistogramEqualized = "Histogram Equalized Image
// Read the image file
Mat image = imread("D:/My OpenCV Website/fly-agaric.jpg");
// Create windows with the above names
namedWindow(windowNameOfOriginalImage, WINDOW_NORMAL);
// Check for failure namedWindow(windowNameOfHistogramEqualized, WINDOW_NORMAL
if (image.empty())
{ // Show images inside created windows.
cout << "Could not open or find the image" << endl;
imshow(windowNameOfOriginalImage, image);
cin.get(); //wait for any key pressimshow(windowNameOfHistogramEqualized, hist_equalized_image);
return -1;
} waitKey(0); // Wait for any keystroke in one of the windows

destroyAllWindows(); //Destroy all open windows

return 0;

Robotic & Vision Lab RoVis


}
//Split the image into 3 channels; Y, Cr and Cb channels respectively and store it
vector<Mat> vec_channels;
split(hist_equalized_image, vec_channels);
include <opencv2/opencv.hpp>
#include <iostream>
//Equalize the histogram of only the Y channel
equalizeHist(vec_channels[0], vec_channels[0]);
using namespace cv;
using namespace std;
//Merge 3 channels in the vector to form the color image in YCrCB color space.
merge(vec_channels, hist_equalized_image);
int main(int argc, char** argv)
{
//Convert the histogram equalized image from YCrCb to BGR color space again
// Read the image file
cvtColor(hist_equalized_image, hist_equalized_image, COLOR_YCrCb2BGR);
Mat image = imread("D:/My OpenCV Website/fly-agaric.jpg");
//Define the names of windows
// Check for failure
String windowNameOfOriginalImage = "Original Image";
if (image.empty())
String windowNameOfHistogramEqualized = "Histogram Equalized Color Image";
{
cout << "Could not open or find the image" << endl;
// Create windows with the above names
cin.get(); //wait for any key press
namedWindow(windowNameOfOriginalImage, WINDOW_NORMAL);
return -1;
namedWindow(windowNameOfHistogramEqualized, WINDOW_NORMAL);
}
// Show images inside the created windows.
//Convert the image from BGR to YCrCb color space
imshow(windowNameOfOriginalImage, image);
Mat hist_equalized_image;
imshow(windowNameOfHistogramEqualized, hist_equalized_image);
cvtColor(image, hist_equalized_image, COLOR_BGR2YCrCb);
waitKey(0); // Wait for any keystroke in any one of the windows

destroyAllWindows(); //Destroy all opened windows

return 0;
}

Robotic & Vision Lab RoVis


Threshold

•Imagine a poker playing robot that needs to visually


interpret the cards in its hand

Original Image Thresholded Image

Robotic & Vision Lab RoVis


Threshold
Giả sử ta có histogram của một hình. Để có thể nhận biết được vật và nền ta có thể sử dụng giải thuật đơn
giản sau:
Nếu pixel có giá trị lớn hơn giá trị ngưỡng T thì nó được gán 1 giá trị thường là mức 1 (255), ngược lại
nhỏ hơn giá trị ngưỡng thì nó được gán 1 giá trị khác thường là mức 0 (0).

Robotic & Vision Lab RoVis


Step to do Threshold
1. Load color image
2. Change to Grey image
3. Threshold

Robotic & Vision Lab RoVis


Ví dụ 2.7: Cho hình sau hãy nhận diện số 200 bằng phân ngưỡng (truy cập Pixel)

#include "opencv2/highgui.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/imgproc.hpp"
#include <iostream>
using namespace cv;
using namespace std;
int main(int argv, char** argc)
{
//Original file
Mat original = imread("threshold.png", CV_LOAD_IMAGE_GRAYSCALE);
//Modified file
Mat modify = imread("threshold.png", CV_LOAD_IMAGE_GRAYSCALE);
//Accessing row
for (int i = 0; i < modify.rows; i++)
{
//Accessing column
for (int k = 0; k < modify.cols; k++)
{
//Pixel with value from 10 to 40
if (modify.at<uint8_t>(i, k) < 210
&& modify.at<uint8_t>(i, k) > 190)
modify.at<uint8_t>(i, k) = 0; //Will be white
else
modify.at<uint8_t>(i, k) = 255; //Other will be black
}
}
imshow("Original", original);
imshow("Theshold", modify);
waitKey(0);

Robotic & Vision Lab RoVis


return 0;
}
Trong thư viện Opencv ta có hàm sau:
double threshold (Mat src, Mat dst, double thresh, double maxval, int type)
Hàm sử dụng là threshold , tham số đầu tiên là 1 ảnh xám, tham số thứ 2 là giá trị ngưỡng,
tham số thứ 3 maxval là giá trị được gán nếu giá pixel lớn hơn giá trị ngưỡng, tham số thứ 4 là
loại phân ngưỡng. Tùy theo các loại phân ngưỡng mà pixel được gán giá trị khác nhau:
•THRESH_BINARY
Nếu giá trị pixel lớn hơn ngưỡng thì gán bằng maxval
Ngược lại bằng gán bằng 0
•THRESH_BINARY_INV
Nếu giá trị pixel lớn hơn ngưỡng thì gán bằng 0
Ngược lại bằng gán bằng maxval
•THRESH_TRUNC
Nếu giá trị pixel lớn hơn ngưỡng thì gán giá trị bằng ngưỡng
Ngược lại giữ nguyên giá trị
•THRESH_TOZERO
Nếu giá trị pixel lớn hơn ngưỡng thì giữ nguyên giá trị
Ngược lại gán bằng 0
THRESH_TOZERO_INV
 Nếu giá trị pixel lớn hơn ngưỡng thì gán giá trị bằng 0
 Ngược lại giữ nguyên

Robotic & Vision Lab RoVis


Cho hình sau
a) Hãy nhận diện số 200 sử dụng hàm opencv
b) Lập trình nhận biết số 64 và 200 của hình

Robotic & Vision Lab RoVis


Basic Adaptive Thresholding
• An approach to handling situations in which
- single value thresholding will not work is to divide an image
into sub images and threshold these individually
• Since the threshold for each pixel depends on its location
within an image this technique is said to adaptive

Robotic & Vision Lab RoVis


0 0 0 0 0 0 0 0 1 1
0 0 0 0 1 0 0 0 1 1
true object boundary 0 0 0 1 1 1 0 0 1 1
0 0 1 1 1 1 1 0 1 1
0 1 1 1 1 1 1 1 1 1
Thresholding 0 1 1 1 1 1 1 1 1 1
1 1 2 2 3 3 4 4 5 5 T = 4.5 0 1 1 1 0 1 1 1 1 1
1 1 2 2 8 3 4 4 5 5
0 1 1 0 0 0 1 1 1 1
1 1 2 7 8 9 4 4 5 5
0 1 0 0 0 0 0 1 1 1
1 1 6 7 8 9 10 4 5 5
0 0 0 0 0 0 0 0 1 1
1 5 6 7 8 9 10 11 5 5
1 5 6 7 8 9 10 11 5 5
0 0 0 0 0 0 0 0 0 0
1 5 6 7 3 9 10 11 5 5
0 0 0 0 1 0 0 0 0 0
1 5 6 2 3 3 10 11 5 5
0 0 0 1 1 1 0 0 0 0
1 5 2 2 3 3 4 11 5 5
0 0 1 1 1 1 1 0 0 0
1 1 2 2 3 3 4 4 5 5 Thresholding 0 0 1 1 1 1 1 1 0 0
T = 5.5 0 0 1 1 1 1 1 1 0 0
0 0 1 1 0 1 1 1 0 0
0 0 1 0 0 0 1 1 0 0
0 0 0 0 0 0 0 1 0 0
0 0 0 0 0 0 0 0 0 0

Robotic & Vision Lab RoVis


– Spatially adaptive thresholding
– Localized processing

1 1 2 2 3 3 4 4 5 5 1 1 2 2 3 3 4 4 5 5
1 1 2 2 8 3 4 4 5 5 1 1 2 2 8 3 4 4 5 5
1 1 2 7 8 9 4 4 5 5 1 1 2 7 8 9 4 4 5 5
1 1 6 7 8 9 10 4 5 5 1 1 6 7 8 9 10 4 5 5
1 5 6 7 8 9 10 11 5 5 Split 1 5 6 7 8 9 10 11 5 5
1 5 6 7 8 9 10 11 5 5
1 5 6 7 8 9 10 11 5 5
1 5 6 7 3 9 10 11 5 5
1 5 6 7 3 9 10 11 5 5
1 5 6 2 3 3 10 11 5 5
1 5 6 2 3 3 10 11 5 5
1 5 2 2 3 3 4 11 5 5
1 5 2 2 3 3 4 11 5 5
1 1 2 2 3 3 4 4 5 5
1 1 2 2 3 3 4 4 5 5

Robotic & Vision Lab RoVis


spatially adaptive threshold selection
0 0 0 0 0 0 0 0 0 0
0 0 0 0 1 0 0 0 0 0
0 0 0 1 1 Thresholding Thresholding 1 0 0 0 0
0 0 1 1 1 T=4 T=7 1 1 0 0 0
0 1 1 1 1 1 1 2 2 3 3 4 4 5 5 1 1 1 0 0

1 1 2 2 8 3 4 4 5 5
1 1 2 7 8 9 4 4 5 5
1 1 6 7 8 9 10 4 5 5
1 5 6 7 8 9 10 11 5 5

1 5 6 7 8 9 10 11 5 5
1 5 6 7 3 9 10 11 5 5
1 5 6 2 3 3 10 11 5 5
1 5 2 2 3 3 4 11 5 5
0 1 1 1 1 1 1 2 2 3 3 4 4 5 5 1 1 1 0 0
0 1 1 1 0 1 1 1 0 0
0 1 1 0 0 Thresholding Thresholding 0 1 1 0 0
0 1 0 0 0 T=4 T=7 0 0 1 0 0
0 0 0 0 0 0 0 0 0 0

Robotic & Vision Lab RoVis


Thresholding Method

merge local segmentation results


0 0 0 0 0 0 0 0 0 0
0 0 0 0 1 0 0 0 0 0
0 0 0 1 1 1 0 0 0 0
merge merge
0 0 1 1 1 1 1 0 0 0
0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0

0 0 0 0 1 0 0 0 0 0
0 0 0 1 1 1 0 0 0 0
0 0 1 1 1 1 1 0 0 0
0 1 1 1 1 1 1 1 0 0
0 1 1 1 1 1 1 1 0 0
0 1 1 1 0 1 1 1 0 0
0 1 1 0 0 0 1 1 0 0
0 1 0 0 0 0 0 1 0 0
0 0 0 0 0 0 0 0 0 0
0 1 1 1 1 1 1 1 0 0
0 1 1 1 0 1 1 1 0 0
merge merge
0 1 1 0 0 0 1 1 0 0
0 1 0 0 0 0 0 1 0 0
0 0 0 0 0 0 0 0 0 0

Robotic & Vision Lab RoVis


Adaptive threshold
applyLocalThresh(cv::Mat &src, cv::Mat& out){
double maxVal, minVal;
cv::Mat output;
int top, bottom, left , right;
int borderType = cv::BORDER_CONSTANT;
cv::Scalar value;
top = (int) (9); bottom = (int) (9);
left = (int) (9); right = (int) (9);
output = src;
out = src;
value = 0;
cv::copyMakeBorder(src,output,top,bottom,left,right,borderType,value);

for(int y = 9; y < src.rows; y++) {

for(int x = 9; x < src.cols; x ++) {

cv::Mat ROI = src(cv::Rect(cv::Point(x-4,y-4),cv::Size(9,9)));


cv::minMaxLoc(ROI,&minVal,&maxVal);

if(src.at<uchar>(cv::Point(x-4,y-4)) >= 0.6*maxVal){

out.at<uchar>(cv::Point(x-4,y-4)) = 255;
}else{
out.at<uchar>(cv::Point(x-4,y-4));

}
}
}
}

Robotic & Vision Lab RoVis


Robotic & Vision Lab RoVis
 Phân ngưỡng theo phương pháp Otsu
o Otsu là tên một nhà nghiên cứu người Nhật đã nghĩ ra ý tưởng cho việc tính ngưỡng T
một cách tự động (adaptive) dựa vào giá trị điểm ảnh của ảnh đầu vào nhằm thay thế cho
việc sử dụng ngưỡng cố định (fixed hay const). Phương pháp này cho kết quả là mỗi ảnh
khác nhau có một ngưỡng tương ứng khác nhau bằng các bước xử lý như sau:
o Chọn một giá trị khởi tạo cho T (nên chọn giá trị mang tính công thức, ví dụ T = (min +
max) / 2, T = giá trị trung bình, ... tránh dùng các giá trị mang tính định lượng thiết lập
cứng).
o Phân hoạch ảnh sử dụng T. kết quả của bước này sẽ tạo ra 2 nhóm điểm ảnh: G1 chứa
tất cả các điểm ảnh với giá trị (intensity) > T và G2 chứa các điểm ảnh với giá trị
(intensity) <= T.
o Tính trung bình (Average hay Mean) m1 và m2 của các điểm ảnh thuộc G1 và G2.
o Tính lại T dựa vào m1 và m2: T = (m1 + m2) / 2
Lặp lại bước 2 đến 4 cho tới khi nào giá trị chênh lệch giữa T củ và T mới là không đáng kể
(nhỏ hơn một giá trị cho trước deltaT). deltaT thường được sử dụng là sai số từ các phép
tính toán trong quá trình

Robotic & Vision Lab RoVis


Using Matlab to do Threshold

Robotic & Vision Lab RoVis


Phân ngưỡng hình sau sử dụng phương pháp Otsu:
• Tính ngưỡng toàn cục theo phương pháp Otsu
• Sử dụng ngưỡng này để threshold hình ảnh
• Vẽ histogram của hình
Kết quả: giá trị ngưỡng tối ưu là 87

t=87 t=100

Robotic & Vision Lab RoVis


HSV Space
• HSV thường được sử dụng trong xử lý ảnh hơn RGB vì:
• HSV giống như cách con người nhận biết màu sắc
• RGB là sự phồi hợp các gam màu và mỗi gam màu bị ảnh hưởng rất lớn bởi độ sáng
• R, G, B in RGB are all co-related to the color luminance( what we loosely call
intensity),i.e., We cannot separate color information from luminance. HSV or Hue
Saturation Value is used to separate image luminance from color information
• HSV là không gian màu được dùng nhiều trong việc chỉnh sửa, phân tích ảnh. Hệ không gian
này dựa vào 3 thông số sau để mô tả màu sắc. H (Hue): màu sắc, S (Saturation) : độ bão
hòa, V (Value): giá trị cường độ sáng .
• Không gian màu này thường được biểu diễn dưới dạng hình trụ hoặc hình nón. Theo đó, đi
theo vòng tròn từ 0 – 3600 là trường biểu diễn màu sắc (Hue), trường này bắt đầu từ màu đỏ.
Các trường S và V trong không gian màu có giá trị biến thiên từ 0 – 1. Các màu đạt giá trị bão
hòa khi S=1 và V=1.

Robotic & Vision Lab RoVis


cv::cvtColor(cv::InputArray src, cv::OutputArray dst, int code)
Trong đó,
o src, dst là ảnh gốc và ảnh thu được sau khi chuyển đổi không gian màu. code mà mã
chuyển đổi không gian màu.
o OpenCV định nghĩa khá nhiều chuyển đổi giữa các không gian màu chẳng hạn như
code = CV_BGR2GRAY sẽ chuyển ảnh ở không gian màu RGB sang ảnh xám, code =
CV_HSV2BGR sẽ chuyển ảnh ở không gian màu HSV sang
 Như vậy để nhận biết màu sắc ta cần
• Convert it to HSV color model
• Define a thresh hold to make it become a binary image with the color we want to
detect
• Filter using Area information to delete noise

Robotic & Vision Lab RoVis


Tìm màu xanh dương trong hình

Robotic & Vision Lab RoVis


int iLowH = 98;
int iHighH = 172;
int iLowS = 94;
int iHighS = 255;
int iLowV = 0;
int iHighV = 255;
while (1)
{
Mat imgOriginal = imread("3d-09-5balls.jpg");
Mat imgHSV;
cvtColor(imgOriginal, imgHSV, COLOR_BGR2HSV); //Convert the captured frame from BGR to HSV
Mat imgThresholded;
namedWindow("Control", CV_WINDOW_AUTOSIZE); //create a window called "Control"
//Create trackbars in "Control" window
cvCreateTrackbar("LowH", "Control", &iLowH, 179); //Hue (0 - 179)
cvCreateTrackbar("HighH", "Control", &iHighH, 179);
cvCreateTrackbar("LowS", "Control", &iLowS, 255); //Saturation (0 - 255)
cvCreateTrackbar("HighS", "Control", &iHighS, 255);
cvCreateTrackbar("LowV", "Control", &iLowV, 255); //Value (0 - 255)
cvCreateTrackbar("HighV", "Control", &iHighV, 255);
inRange(imgHSV, Scalar(iLowH, iLowS, iLowV), Scalar(iHighH, iHighS, iHighV), imgThresholded); //Threshold the image
find_moments(imgThresholded);
namedWindow("threshold", CV_WINDOW_AUTOSIZE);
imshow("threshold", imgThresholded);
waitKey(10);
}
return(0);
}

Robotic & Vision Lab RoVis


#include <iostream>
#include "opencv2/highgui/highgui.hpp" Tìm màu đỏ trong video
#include "opencv2/imgproc/imgproc.hpp"

using namespace cv;


using namespace std;

int main( int argc, char** argv )


{
VideoCapture cap(0); //capture the video from web cam

if ( !cap.isOpened() ) // if not success, exit program


{
cout << "Cannot open the web cam" << endl;
return -1;
}

namedWindow("Control", CV_WINDOW_AUTOSIZE); //create a window called "Control"

int iLowH = 0;
int iHighH = 179;

int iLowS = 0;
int iHighS = 255;

int iLowV = 0;
int iHighV = 255;

//Create trackbars in "Control" window


cvCreateTrackbar("LowH", "Control", &iLowH, 179); //Hue (0 - 179)
cvCreateTrackbar("HighH", "Control", &iHighH, 179);
Robotic & Vision Lab RoVis
cvCreateTrackbar("LowS", "Control", &iLowS, 255); //Saturation (0 - 255)
cvCreateTrackbar("HighS", "Control", &iHighS, 255);

cvCreateTrackbar("LowV", "Control", &iLowV, 255); //Value (0 - 255)


cvCreateTrackbar("HighV", "Control", &iHighV, 255);

while (true)
{
Mat imgOriginal;

bool bSuccess = cap.read(imgOriginal); // read a new frame from video

if (!bSuccess) //if not success, break loop


{
cout << "Cannot read a frame from video stream" << endl;
break;
}

Mat imgHSV;

cvtColor(imgOriginal, imgHSV, COLOR_BGR2HSV); //Convert the captured frame from BGR to HSV

Mat imgThresholded;

inRange(imgHSV, Scalar(iLowH, iLowS, iLowV), Scalar(iHighH, iHighS, iHighV),


imgThresholded); //Threshold the image

//morphological opening (remove small objects from the foreground)

Robotic & Vision Lab RoVis


erode(imgThresholded, imgThresholded, getStructuringElement(MORPH_ELLIPSE,
Size(5, 5)) );
dilate( imgThresholded, imgThresholded, getStructuringElement(MORPH_ELLIPSE,
Size(5, 5)) );

//morphological closing (fill small holes in the foreground)


dilate( imgThresholded, imgThresholded, getStructuringElement(MORPH_ELLIPSE,
Size(5, 5)) );
erode(imgThresholded, imgThresholded, getStructuringElement(MORPH_ELLIPSE,
Size(5, 5)) );

imshow("Thresholded Image", imgThresholded); //show the thresholded image

imshow("Original", imgOriginal); //show the original image

if (waitKey(30) == 27) //wait for 'esc' key press for 30ms. If 'esc' key is pressed,
break loop
{
cout << "esc key is pressed by user" << endl;
break;
}
}

return 0;

}
Robotic & Vision Lab RoVis
Tìm 2 màu đỏ và xanh lá cây trong hình cùng một lúc

Robotic & Vision Lab RoVis


Bài Tập: a) load 2 hình và tính khoảng cách Euclide giữa 2 màu (R,G,B)

b) Set threshold để thấy cánh tay

Robotic & Vision Lab RoVis


cv::Mat diffImage;
cv::absdiff(backgroundImage, currentImage, diffImage);

cv::Mat foregroundMask = cv::Mat::zeros(diffImage.rows, diffImage.cols, CV_8UC1);

float threshold = 30.0f;


float dist;

for(int j=0; j<diffImage.rows; ++j)


for(int i=0; i<diffImage.cols; ++i)
{
cv::Vec3b pix = diffImage.at<cv::Vec3b>(j,i);

dist = (pix[0]*pix[0] + pix[1]*pix[1] + pix[2]*pix[2]);


dist = sqrt(dist);

if(dist>threshold)
{
foregroundMask.at<unsigned char>(j,i) = 255;
}
}
Robotic & Vision Lab RoVis
Ví dụ 10.3: lọc RGB hình người và chèn vào hình nền

cvInRangeS(objectImage, lowerValue, upperValue, maskImage);

cvSetZero(extractedBackgroundImage);
cvCopy(backgroundImage, extractedBackgroundImage, maskImage);
cvNot(maskImage, inverseMaskImage);
cvSetZero(extractedObjectImage);
cvCopy(objectImage, extractedObjectImage, inverseMaskImage);
cvAdd(extractedBackgroundImage, extractedObjectImage, destinationImage, NULL);

cvShowImage(windowNameExtract, extractedObjectImage);
cvShowImage(windowresultadd, destinationImage);

Robotic & Vision Lab RoVis

You might also like