text:
Nhận diện khung truyện manga với OpenCV
Đọc manga trên mobile là một nhu cầu rất lớn, nhưng hiện nay chưa có nhiều ứng dụng đáp ứng được nhu cầu này một cách hiệu quả.
Vấn đề
Một trong những vấn đề lớn nhất của việc đọc manga trên các thiết bị mobile màn hình nhỏ (điện thoại, máy đọc sách,...) là kích thước của một trang truyện thường khá lớn, và màn hình thì rất nhỏ nên dẫn đến nhiều bất tiện khi đọc. Nhất là khi sử dụng điện thoại trong portrait mode (chiều dọc), vì lúc này chữ trong các khung truyện rất nhỏ, dẫn đến hoàn toàn không đọc được.
Giải pháp mà đa số các app sử dụng lúc này là đọc truyện trong landscape mode (nằm ngang), điều này tạm giải quyết được vấn đề kích thước, tuy nhiên một khung truyện vẫn rất nhỏ để đọc. Chỉ có một cách là người dùng phải tự tay zoom đến từng ô truyện nếu muốn đọc thoải mái, rất phiền phức. Thêm nữa, việc sử dụng điện thoại khi đọc truyện trong landscape mode trong thời gian dài cũng không phải là một ý kiến hay cho lắm.
Trên các máy đọc sách như Kindle Paperwhite, thì Amazon giải quyết bằng một cách khác, đó là cho phép user thực hiện double tap để zoom to từng góc của một trang truyện, tap thêm một cái thì sẽ dịch chuyển khung màn hình sang một góc khác, cứ như thế đi đến 4 góc của màn hình.
Và với cách này thì các vùng hiển thị sẽ bị chồng chéo, giống như hình trên, khi Kindle hiển thị vùng số 2, một phần nội dung của vùng số 1 vẫn bị dính vào khung hình. Không đem lại cảm giác đọc truyện thoải mái cho người dùng.
Giải pháp
Chắc sẽ có rất nhiều giải pháp để giải quyết vấn đề này, trong bài này mình chỉ trình bày giải pháp do mình đề xuất, đó là tách từng khung truyện ra để hiển thị độc lập trên màn hình.
Như hình minh họa trên, chúng ta sẽ dùng một cách nào đó (sẽ nói ở phần tiếp theo của bài viết) để phân tách một trang truyện thành từng khung nhỏ, và hiển thị độc lập từng khung (hoặc có thể hiển thị toàn trang nhưng focus vào trung tâm của từng khung truyện), mang lại trải nghiệm đọc tốt hơn cho người dùng.
Về ý tưởng thì hoàn toàn hợp lý và không có gì phức tạp cho lắm, nếu các khung truyện chỉ đơn giản là các hình chữ nhật, thì việc tìm và bóc tách khung truyện cũng sẽ rất dễ dàng. Tuy nhiên đa số các manga hiện nay đều sử dụng rất ít bố cục lưới hình chữ nhật ngay ngắn, mà một khung truyện thường sẽ đa dạng như hình minh họa ở trên.
Bài viết này sẽ trình bày về cách implement thuật toán nhận diện khung truyện sử dụng OpenCV, có thể làm việc được với các hình khối của từng khung truyện đa dạng như trên.
Implementation
Sở dĩ chọn OpenCV là vì nó cung cấp cho chúng ta rất nhiều hàm/thuật toán xử lý hình ảnh cơ bản, và ở giai đoạn này chúng ta chỉ prototype thuật toán nhận diện, chưa đi sâu vào việc implement nó vào một ứng dụng thực tế nào, nên có thể sử dụng nó thoải mái. Khi đã hình thành được phương pháp giải quyết thì chúng ta có thể tự implement toàn bộ các thuật toán liên quan nếu thích.
Load trang truyện vào OpenCV
Việc đầu tiên cần làm đó là load trang truyện cần xử lý vào OpenCV, ở đây chúng ta sử dụng Python và thư viện OpenCV 2.
Giả sử chúng ta đã có file
manga.jpg nằm cùng thư mục với chương trình Python:
import cv2 import numpy as np img = cv2.imread('manga.jpg') print img.shape
Chúng ta sử dụng hàm
cv2.imread để đọc file hình ảnh, đối tượng
img bây giờ sẽ là một mảng các pixel màu theo định dạng BGR (blue, green, red). Thuộc tính
shape của
img trả về một tuple gồm các thông tin về kích thước (số dòng, số cột) của mảng pixel, và số channel (kênh màu) trong hình đó.
Ở ví dụ trên, kết quả trả về sẽ là:
(1150, 802, 3)
Tức là hình ảnh có chiều dài 1150 pixel, rộng 802 pixel và có 3 kênh màu.
Mặc dù trang truyện trên là trắng đen, nhưng màu sắc mặc định của một hình ảnh sẽ có 3 kênh, quá nhiều kênh màu cũng sẽ gây cản trở cho việc xử lý vì thế chúng ta có thể convert hình ảnh trên về định dạng trắng đen (grayscale) thực sự:
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) print img.shape
Lúc này output sẽ chỉ còn:
(1150, 802)
Vì là ảnh grayscale nên số channel không được hiển thị.
Để hiển thị hình ảnh vừa load lên màn hình, có thể sử dụng thư viện
matplotlib như sau:
import cv2 import numpy as np from matplotlib import pyplot as plt img = cv2.imread('manga.jpg') plt.subplot(111), plt.imshow(img) plt.show()
Hình ảnh sẽ được hiện lên qua một cửa sổ mới như sau:
Tiếp theo chúng ta sẽ thử qua một vài phép xử lý ảnh đơn giản.
Thresholding
Một phương pháp xử lý ảnh đơn giản đó là thresholding, đây là thuật toán dùng để lọc từng pixel của một hình ảnh đen trắng theo một ngưỡng nào đó, nếu pixel đang xét có giá trị thấp hơn ngưỡng đã chỉ định, nó sẽ gán pixel đó thành một màu, nếu pixel đó có giá trị lớn hơn ngưỡng đã chỉ định, nó sẽ gán pixel đó về một màu khác.
Chúng ta có thể sử dụng thresholding để lọc bớt các chi tiết màu xám trong trang truyện để nó hoàn toàn trở về 2 màu đen và trắng. Như vậy ở bước nhận diện khung truyện chúng ta sẽ có kết quả chính xác hơn.
Việc thresholding được thực hiện thông qua hàm cv2.threshold, hàm này có dạng:
ret, thresh = cv2.threshold(img, <classify value>, <max value>, <type>)
Tham số đầu tiên là đối tượng
img, tức là hình ảnh đầu vào cần xử lý, tham số thứ 2
classify value là giá trị màu trong khoảng từ $0 \rightarrow 255$ (đen đến trắng) dùng làm ngưỡng phân biệt, tham số thứ 3 là giá trị sẽ được gán cho pixel đang xét nếu nó lớn hơn giá trị classify, ở đây chúng ta có thể dùng 255 tức là màu trắng. Cuối cùng là tham số type, nhận vào một trong các giá trị:
- cv2.THRESH_BINARY
- cv2.THRESH_BINARY_INV
- cv2.THRESH_TRUNC
- cv2.THRESH_TOZERO
- cv2.THRESH_TOZERO_INV
Chúng ta sẽ thử apply thuật toán thresholding với tham số
THRESH_BINARY và xem kết quả:
import cv2 import numpy as np from matplotlib import pyplot as plt img = cv2.imread('manga.jpg') img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) ret,thresh = cv2.threshold(img, 90, 255, cv2.THRESH_BINARY) plt.subplot(121), plt.imshow(img, cmap='Greys_r') plt.subplot(122), plt.imshow(thresh, cmap='Greys_r') plt.show()
Chạy thử sẽ thấy các chi tiết màu xám (như phần lửa ở khung truyện giữa) đã bị lọc bỏ:
Tuy nhiên các thành phần như watermark vẫn còn, để lấy khung hình chính xác hơn, chúng ta có thể tạm thời loại bỏ chúng ra khỏi vùng xác định (tất nhiên chúng ta sẽ không thay đổi bất kì nội dung nào của trang truyện khi implement trên ứng dụng thực tế cả)
Đồng thời, để phục vụ cho bước tiếp theo, chúng ta cũng sẽ thay giá trị
cv2.THRESH_BINARY thành
cv2.THRESH_BINARY_INV để đảo ngược màu sắc trong khung truyện, lý do sẽ giải thích ở bước tiếp theo.
ret,thresh = cv2.threshold(img, 80, 255, cv2.THRESH_BINARY_INV)
Hạ giá trị ngưỡng màu xuống một tí để lọc các phần màu sáng hơn, kết quả có vẻ khả quan hơn:
Xác định Contours
Contours là đường bao kết nối tất cả các điểm liền kề nhau có cùng màu sắc hoặc độ tương phản. Chính vì đặc tính này, contours thường được dùng trong xác định vật thể, nhận dạng,...
Trong trường hợp này chúng ta cũng sẽ dùng thuật toán xác định contours làm nền tảng để xác định các khung truyện.
Trong OpenCV, thuật toán tìm contours hoạt động dựa trên các chi tiết có màu trắng, trên nền màu đen. Chính vì vậy ở phần trước, khi thực hiện thresholding, chúng ta đã đảo màu nền và màu nét của trang truyện.
Chúng ta sẽ dùng hàm cv2.findContours() để tìm hết tất cả contours trong hình, và dùng hàm cv2.drawContours() để vẽ các contours tìm được lên hình. Chi tiết về 2 hàm này các bạn có thể xem tại đây.
import cv2 import numpy as np from matplotlib import pyplot as plt orig = cv2.imread('manga.jpg') img = cv2.imread('manga.jpg') result = cv2.imread('manga.jpg') img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) ret,thresh = cv2.threshold(img, 80, 255, cv2.THRESH_BINARY_INV) contours, h = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) for cnt in contours: cv2.drawContours(result, [cnt], -1, 255, -1) plt.subplot(121), plt.imshow(orig) plt.subplot(122), plt.imshow(result) plt.show()
Phần màu đỏ chính là phần contours tìm được sau khi sử dụng thuật toán findContours. Ở đây mình dùng hàm drawContours để vẽ đè phần contours lên trên hình gốc để dễ hình dung:
Tuy nhiên, với các contours như trên, chúng ta vẫn rất khó để phân biệt được đâu là khung truyện chính xác, cần có một phương pháp hiệu quả hơn.
Convex Hull
Convex Hull là một đường xấp xỉ bao quanh contours, và có ít đỉnh hơn, tạo ra một hình khối tổng quát của contour đó.
Ta sẽ áp dụng convex hull để xác định các đường bao quanh các contours trong một khung truyện, bằng cách này ta có thể xác định được chính xác hơn.
Để tìm convex hull của một contour, chúng ta sử dụng hàm cv2.convexHull(), chi tiết về hàm này có thể xem tại đây.
for cnt in contours: hull = cv2.convexHull(cnt) cv2.drawContours(result, [cnt], -1, 255, -1) cv2.drawContours(result, [hull], -1, 255, -1)
Kết quả là chúng ta đã xác định được một cách tương đối chính xác từng ô truyện như hình sau:
Một số ô truyện vẫn còn bị cắt vào phần nội dung, lý do là chúng ta chưa xác định rõ phần viền của nội dung một trang truyện, và bị cắt xén trong quá trình thresholding. Vấn đề này sẽ được nói chi tiết hơn ở các bài sau.
Các bạn có thể tham khảo mã nguồn đầy đủ tại đây:
import cv2 import numpy as np from matplotlib import pyplot as plt filename = 'manga.jpg' orig = cv2.imread(filename) img = cv2.imread(filename) result = cv2.imread(filename) img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) ret,thresh = cv2.threshold(img, 80, 255, cv2.THRESH_BINARY_INV) contours, h = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) for cnt in contours: hull = cv2.convexHull(cnt) cv2.drawContours(result, [cnt], -1, 255, -1) cv2.drawContours(result, [hull], -1, 255, -1) plt.subplot(121), plt.imshow(orig) plt.subplot(122), plt.imshow(result) plt.show()
Thử nghiệm
Đối với các trang truyện có khung hình đã được canh chỉnh cách xa đường viền của trang, thì thuật toán hoạt động rất hiệu quả:
Đối với các truyện có nội dung tràn lề, thuật toán bắt đầu hoạt động kém hiệu quả:
Đặc biệt đối với những truyện có layout hoàn toàn bất thường như 2 ví dụ dưới đây thì thuật toán gần như không hoạt động 😭
Kết luận
Tạm thời chúng ta đã thu được kết quả nhất định, thuật toán hoạt động ổn trong một số trường hợp, tuy nhiên với óc sáng tạo của các mangaka, việc bố trí layout cho một trang truyện có thể biến đổi khôn lường, đến lúc này thì thuật toán của chúng ta cần phải có cách giải quyết hiệu quả hơn.
Ngoài 2 trường hợp đặc biệt cuối cùng, thuật toán cần cải thiện việc xử lý khung viền đối với những trang truyện có nội dung tràn lề (như ví dụ 3), ở bài viết tới, chúng ta sẽ cùng tìm hiểu về cách tự động vẽ lại nội dung đường viền để khắc phục tình trạng này.
Dữ liệu cho các ví dụ minh hoạt thuật toán ở trong bài viết được lấy từ các manga One Piece chapter 846 và GTO: Paradise Lost chap 42 từ trang TruyenTranhTuan. Việc sử dụng chỉ nhằm mục đích nghiên cứu khoa học, không hề có sự đồng thuận từ phía các tác giả Eiichiro Oda, Fujisawa Tooru hay từ phía các nhà xuất bản.
Có thể trích dẫn nguyên văn hoặc share lại với điều kiện không được sửa đổi bất kì nội dung nào, và không được sử dụng với mục đích thương mại.

markdown:
# Nhận diện khung truyện manga với OpenCV
**Published:**11/17/2016 11:59:25 PM
Đọc manga trên mobile là một nhu cầu rất lớn, nhưng hiện nay chưa có nhiều ứng dụng đáp ứng được nhu cầu này một cách hiệu quả.
## Vấn đề
Một trong những vấn đề lớn nhất của việc đọc manga trên các thiết bị mobile màn hình nhỏ (điện thoại, máy đọc sách,...) là kích thước của một trang truyện thường khá lớn, và màn hình thì rất nhỏ nên dẫn đến nhiều bất tiện khi đọc. Nhất là khi sử dụng điện thoại trong portrait mode (chiều dọc), vì lúc này chữ trong các khung truyện rất nhỏ, dẫn đến hoàn toàn không đọc được.
Giải pháp mà đa số các app sử dụng lúc này là đọc truyện trong landscape mode (nằm ngang), điều này tạm giải quyết được vấn đề kích thước, tuy nhiên một khung truyện vẫn rất nhỏ để đọc. Chỉ có một cách là người dùng phải tự tay zoom đến từng ô truyện nếu muốn đọc thoải mái, rất phiền phức. Thêm nữa, việc sử dụng điện thoại khi đọc truyện trong landscape mode trong thời gian dài cũng không phải là một ý kiến hay cho lắm.
Trên các máy đọc sách như Kindle Paperwhite, thì Amazon giải quyết bằng một cách khác, đó là cho phép user thực hiện double tap để zoom to từng góc của một trang truyện, tap thêm một cái thì sẽ dịch chuyển khung màn hình sang một góc khác, cứ như thế đi đến 4 góc của màn hình.
Và với cách này thì các vùng hiển thị sẽ bị chồng chéo, giống như hình trên, khi Kindle hiển thị vùng số 2, một phần nội dung của vùng số 1 vẫn bị dính vào khung hình. Không đem lại cảm giác đọc truyện thoải mái cho người dùng.
## Giải pháp
Chắc sẽ có rất nhiều giải pháp để giải quyết vấn đề này, trong bài này mình chỉ trình bày giải pháp do mình đề xuất, đó là
**tách từng khung truyện ra để hiển thị độc lập trên màn hình**.
Như hình minh họa trên, chúng ta sẽ dùng một cách nào đó (sẽ nói ở phần tiếp theo của bài viết) để phân tách một trang truyện thành từng khung nhỏ, và hiển thị độc lập từng khung (hoặc có thể hiển thị toàn trang nhưng focus vào trung tâm của từng khung truyện), mang lại trải nghiệm đọc tốt hơn cho người dùng.
Về ý tưởng thì hoàn toàn hợp lý và không có gì phức tạp cho lắm, nếu các khung truyện chỉ đơn giản là các hình chữ nhật, thì việc tìm và bóc tách khung truyện cũng sẽ rất dễ dàng. Tuy nhiên đa số các manga hiện nay đều sử dụng rất ít bố cục lưới hình chữ nhật ngay ngắn, mà một khung truyện thường sẽ đa dạng như hình minh họa ở trên.
Bài viết này sẽ trình bày về cách implement thuật toán nhận diện khung truyện sử dụng OpenCV, có thể làm việc được với các hình khối của từng khung truyện đa dạng như trên.
## Implementation
Sở dĩ chọn OpenCV là vì nó cung cấp cho chúng ta rất nhiều hàm/thuật toán xử lý hình ảnh cơ bản, và ở giai đoạn này chúng ta chỉ prototype thuật toán nhận diện, chưa đi sâu vào việc implement nó vào một ứng dụng thực tế nào, nên có thể sử dụng nó thoải mái. Khi đã hình thành được phương pháp giải quyết thì chúng ta có thể tự implement toàn bộ các thuật toán liên quan nếu thích.
### Load trang truyện vào OpenCV
Việc đầu tiên cần làm đó là load trang truyện cần xử lý vào OpenCV, ở đây chúng ta sử dụng Python và thư viện OpenCV 2.
Giả sử chúng ta đã có file
manga.jpg nằm cùng thư mục với chương trình Python:
import cv2 import numpy as np img = cv2.imread('manga.jpg') print img.shape
Chúng ta sử dụng hàm
cv2.imread để đọc file hình ảnh, đối tượng
img bây giờ sẽ là một mảng các pixel màu theo định dạng
**BGR** (blue, green, red). Thuộc tính
shape của
img trả về một tuple gồm các thông tin về kích thước (số dòng, số cột) của mảng pixel, và số channel (kênh màu) trong hình đó.
Ở ví dụ trên, kết quả trả về sẽ là:
(1150, 802, 3)
Tức là hình ảnh có chiều dài 1150 pixel, rộng 802 pixel và có 3 kênh màu.
Mặc dù trang truyện trên là trắng đen, nhưng màu sắc mặc định của một hình ảnh sẽ có 3 kênh, quá nhiều kênh màu cũng sẽ gây cản trở cho việc xử lý vì thế chúng ta có thể convert hình ảnh trên về định dạng trắng đen (grayscale) thực sự:
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) print img.shape
Lúc này output sẽ chỉ còn:
(1150, 802)
Vì là ảnh grayscale nên số channel không được hiển thị.
Để hiển thị hình ảnh vừa load lên màn hình, có thể sử dụng thư viện
matplotlib như sau:
import cv2 import numpy as np from matplotlib import pyplot as plt img = cv2.imread('manga.jpg') plt.subplot(111), plt.imshow(img) plt.show()
Hình ảnh sẽ được hiện lên qua một cửa sổ mới như sau:
Tiếp theo chúng ta sẽ thử qua một vài phép xử lý ảnh đơn giản.
### Thresholding
Một phương pháp xử lý ảnh đơn giản đó là thresholding, đây là thuật toán dùng để lọc từng pixel của một hình ảnh đen trắng theo một ngưỡng nào đó, nếu pixel đang xét có giá trị thấp hơn ngưỡng đã chỉ định, nó sẽ gán pixel đó thành một màu, nếu pixel đó có giá trị lớn hơn ngưỡng đã chỉ định, nó sẽ gán pixel đó về một màu khác.
Chúng ta có thể sử dụng thresholding để lọc bớt các chi tiết màu xám trong trang truyện để nó hoàn toàn trở về 2 màu đen và trắng. Như vậy ở bước nhận diện khung truyện chúng ta sẽ có kết quả chính xác hơn.
Việc thresholding được thực hiện thông qua hàm
**cv2.threshold**, hàm này có dạng:
ret, thresh = cv2.threshold(img, <classify value>, <max value>, <type>)
Tham số đầu tiên là đối tượng
img, tức là hình ảnh đầu vào cần xử lý, tham số thứ 2
classify value là giá trị màu trong khoảng từ
**$0 \rightarrow 255$** (đen đến trắng) dùng làm ngưỡng phân biệt, tham số thứ 3 là giá trị sẽ được gán cho pixel đang xét nếu nó lớn hơn giá trị classify, ở đây chúng ta có thể dùng **255** tức là màu trắng. Cuối cùng là tham số type, nhận vào một trong các giá trị:
- cv2.THRESH_BINARY
- cv2.THRESH_BINARY_INV
- cv2.THRESH_TRUNC
- cv2.THRESH_TOZERO
- cv2.THRESH_TOZERO_INV
Chúng ta sẽ thử apply thuật toán thresholding với tham số
THRESH_BINARY và xem kết quả:
import cv2 import numpy as np from matplotlib import pyplot as plt img = cv2.imread('manga.jpg') img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) ret,thresh = cv2.threshold(img, 90, 255, cv2.THRESH_BINARY) plt.subplot(121), plt.imshow(img, cmap='Greys_r') plt.subplot(122), plt.imshow(thresh, cmap='Greys_r') plt.show()
Chạy thử sẽ thấy các chi tiết màu xám (như phần lửa ở khung truyện giữa) đã bị lọc bỏ:
Tuy nhiên các thành phần như watermark vẫn còn, để lấy khung hình chính xác hơn, chúng ta có thể tạm thời loại bỏ chúng ra khỏi vùng xác định (tất nhiên chúng ta sẽ không thay đổi bất kì nội dung nào của trang truyện khi implement trên ứng dụng thực tế cả)
Đồng thời, để phục vụ cho bước tiếp theo, chúng ta cũng sẽ thay giá trị
cv2.THRESH_BINARY thành
cv2.THRESH_BINARY_INV để đảo ngược màu sắc trong khung truyện, lý do sẽ giải thích ở bước tiếp theo.
ret,thresh = cv2.threshold(img, 80, 255, cv2.THRESH_BINARY_INV)
Hạ giá trị ngưỡng màu xuống một tí để lọc các phần màu sáng hơn, kết quả có vẻ khả quan hơn:
### Xác định Contours
Contours là đường bao kết nối tất cả các điểm liền kề nhau có cùng màu sắc hoặc độ tương phản. Chính vì đặc tính này, contours thường được dùng trong xác định vật thể, nhận dạng,...
Trong trường hợp này chúng ta cũng sẽ dùng thuật toán xác định contours làm nền tảng để xác định các khung truyện.
Trong OpenCV, thuật toán tìm contours hoạt động dựa trên các chi tiết có màu trắng, trên nền màu đen. Chính vì vậy ở phần trước, khi thực hiện thresholding, chúng ta đã đảo màu nền và màu nét của trang truyện.
Chúng ta sẽ dùng hàm
**cv2.findContours()** để tìm hết tất cả contours trong hình, và dùng hàm **cv2.drawContours()** để vẽ các contours tìm được lên hình. Chi tiết về 2 hàm này các bạn có thể xem tại [đây](https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_imgproc/py_contours/py_contours_begin/py_contours_begin.html#contours-getting-started).
import cv2 import numpy as np from matplotlib import pyplot as plt orig = cv2.imread('manga.jpg') img = cv2.imread('manga.jpg') result = cv2.imread('manga.jpg') img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) ret,thresh = cv2.threshold(img, 80, 255, cv2.THRESH_BINARY_INV) contours, h = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) for cnt in contours: cv2.drawContours(result, [cnt], -1, 255, -1) plt.subplot(121), plt.imshow(orig) plt.subplot(122), plt.imshow(result) plt.show()
Phần màu đỏ chính là phần contours tìm được sau khi sử dụng thuật toán findContours. Ở đây mình dùng hàm
**drawContours** để vẽ đè phần contours lên trên hình gốc để dễ hình dung:
Tuy nhiên, với các contours như trên, chúng ta vẫn rất khó để phân biệt được đâu là khung truyện chính xác, cần có một phương pháp hiệu quả hơn.
### Convex Hull
Convex Hull là một đường xấp xỉ bao quanh contours, và có ít đỉnh hơn, tạo ra một hình khối tổng quát của contour đó.
Ta sẽ áp dụng convex hull để xác định các đường bao quanh các contours trong một khung truyện, bằng cách này ta có thể xác định được chính xác hơn.
Để tìm convex hull của một contour, chúng ta sử dụng hàm
**cv2.convexHull()**, chi tiết về hàm này có thể xem tại [đây](https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_imgproc/py_contours/py_contour_features/py_contour_features.html?highlight=convex%20hull).
for cnt in contours: hull = cv2.convexHull(cnt) cv2.drawContours(result, [cnt], -1, 255, -1) cv2.drawContours(result, [hull], -1, 255, -1)
Kết quả là chúng ta đã xác định được một cách tương đối chính xác từng ô truyện như hình sau:
Một số ô truyện vẫn còn bị cắt vào phần nội dung, lý do là chúng ta chưa xác định rõ phần viền của nội dung một trang truyện, và bị cắt xén trong quá trình thresholding. Vấn đề này sẽ được nói chi tiết hơn ở các bài sau.
Các bạn có thể tham khảo mã nguồn đầy đủ tại đây:
import cv2 import numpy as np from matplotlib import pyplot as plt filename = 'manga.jpg' orig = cv2.imread(filename) img = cv2.imread(filename) result = cv2.imread(filename) img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) ret,thresh = cv2.threshold(img, 80, 255, cv2.THRESH_BINARY_INV) contours, h = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) for cnt in contours: hull = cv2.convexHull(cnt) cv2.drawContours(result, [cnt], -1, 255, -1) cv2.drawContours(result, [hull], -1, 255, -1) plt.subplot(121), plt.imshow(orig) plt.subplot(122), plt.imshow(result) plt.show()
## Thử nghiệm
Đối với các trang truyện có khung hình đã được canh chỉnh cách xa đường viền của trang, thì thuật toán hoạt động rất hiệu quả:
Đối với các truyện có nội dung tràn lề, thuật toán bắt đầu hoạt động kém hiệu quả:
Đặc biệt đối với những truyện có layout hoàn toàn bất thường như 2 ví dụ dưới đây thì thuật toán gần như không hoạt động 😭
## Kết luận
Tạm thời chúng ta đã thu được kết quả nhất định, thuật toán hoạt động ổn trong một số trường hợp, tuy nhiên với óc sáng tạo của các mangaka, việc bố trí layout cho một trang truyện có thể biến đổi khôn lường, đến lúc này thì thuật toán của chúng ta cần phải có cách giải quyết hiệu quả hơn.
Ngoài 2 trường hợp đặc biệt cuối cùng, thuật toán cần cải thiện việc xử lý khung viền đối với những trang truyện có nội dung tràn lề (như ví dụ 3), ở bài viết tới, chúng ta sẽ cùng tìm hiểu về cách tự động vẽ lại nội dung đường viền để khắc phục tình trạng này.
Dữ liệu cho các ví dụ minh hoạt thuật toán ở trong bài viết được lấy từ các manga
**One Piece** chapter 846 và **GTO: Paradise Lost** chap 42 từ trang [TruyenTranhTuan](http://truyentranhtuan.com). Việc sử dụng chỉ nhằm mục đích nghiên cứu khoa học, không hề có sự đồng thuận từ phía các tác giả Eiichiro Oda, Fujisawa Tooru hay từ phía các nhà xuất bản. [Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License](http://creativecommons.org/licenses/by-nc-sa/4.0/)
Có thể trích dẫn nguyên văn hoặc share lại với điều kiện không được sửa đổi bất kì nội dung nào, và không được sử dụng với mục đích thương mại.
Ctrl+ Enterđể gửi.

Server: nginx/1.9.3 (Ubuntu)

Accept-Ranges: bytes


text:
Kỹ năng bán hàng
Kỹ năng bán hàng Kỹ năng mềm
5 bước giành lại khách hàng đã mất hiệu quả nhất
(Tự Học Marketing) – Hiện nay, bạn đang mong muốn tìm cách nào đó để thu hút lại những khách hàng lâu rồi không ghé mua hàng tại cửa hàng,
Kỹ năng bán hàng
Những sai lầm cần tránh khi giao dịch với khách hàng
(Tự Học Marketing) – Trong bán hàng sai lầm là một điều tất yếu phải xảy ra nhưng để nhận biết được sai lầm có thể xảy ra trước và
Kỹ năng bán hàng Kỹ năng mềm
Cách Trả Giá Trong Đàm Phán
(Tự Học Marketing) – Hôm nay, mình sẽ hướng dẫn cho bạn cách trả giá trong đàm phán sao cho hiệu quả và thành công nhất rất chi tiết ở
Kỹ năng bán hàng
Bí quyết thu hút khách hàng khi bán hàng trên mạng
Tự học marketing – Sự phát triển mạnh mẽ của internet đã đem lại sắc màu mới cho việc kinh doanh trên mạng ngày càng phát triển, việc bán hàng
Kỹ năng bán hàng Kỹ năng mềm
Cách Marketing Khách Hàng Mới Như Thế Nào Hiệu Quả Nhất
Tự Học Marketing – Chắc hẳn là bạn đang phân vân không biết nên marketing khách hàng mới như thế nào cho hiệu quả chính xác nhất? Vậy thì ngay

markdown:
## Kỹ năng bán hàng
[Back to homepage](https://tuhocmarketing.com) [](https://tuhocmarketing.com/ky-nang-mem/ky-nang-ban-hang) **Kỹ năng bán hàng** [](https://tuhocmarketing.com/ky-nang-mem) **Kỹ năng mềm**
###
[5 bước giành lại khách hàng đã mất hiệu quả nhất](https://tuhocmarketing.com/ky-nang-mem/299-5-bc-ginh-li-khch-hng-mt-hiu-qu-nht.html)
(Tự Học Marketing) – Hiện nay, bạn đang mong muốn tìm cách nào đó để thu hút lại những khách hàng lâu rồi không ghé mua hàng tại cửa hàng,
[](https://tuhocmarketing.com/ky-nang-mem/ky-nang-ban-hang) **Kỹ năng bán hàng**
###
[Những sai lầm cần tránh khi giao dịch với khách hàng](https://tuhocmarketing.com/ky-nang-mem/ky-nang-ban-hang/220-nhng-sai-lm-cn-trnh-khi-giao-dch-vi-khch-hng.html)
(Tự Học Marketing) – Trong bán hàng sai lầm là một điều tất yếu phải xảy ra nhưng để nhận biết được sai lầm có thể xảy ra trước và
[](https://tuhocmarketing.com/ky-nang-mem/ky-nang-ban-hang) **Kỹ năng bán hàng** [](https://tuhocmarketing.com/ky-nang-mem) **Kỹ năng mềm**
###
[Cách Trả Giá Trong Đàm Phán](https://tuhocmarketing.com/ky-nang-mem/173-cch-tr-gi-trong-phn.html)
(Tự Học Marketing) – Hôm nay, mình sẽ hướng dẫn cho bạn cách trả giá trong đàm phán sao cho hiệu quả và thành công nhất rất chi tiết ở
[](https://tuhocmarketing.com/ky-nang-mem/ky-nang-ban-hang) **Kỹ năng bán hàng**
###
[Bí quyết thu hút khách hàng khi bán hàng trên mạng](https://tuhocmarketing.com/ky-nang-mem/ky-nang-ban-hang/166-quyt-thu-ht-khch-hng-khi-bn-hng-trn-mng.html)
Tự học marketing – Sự phát triển mạnh mẽ của internet đã đem lại sắc màu mới cho việc kinh doanh trên mạng ngày càng phát triển, việc bán hàng
[](https://tuhocmarketing.com/ky-nang-mem/ky-nang-ban-hang) **Kỹ năng bán hàng** [](https://tuhocmarketing.com/ky-nang-mem) **Kỹ năng mềm**
###
[Cách Marketing Khách Hàng Mới Như Thế Nào Hiệu Quả Nhất](https://tuhocmarketing.com/ky-nang-mem/95-cach-marketing-khach-hang-moi-nhu-the-nao-hieu-qua-nhat.html)
Tự Học Marketing – Chắc hẳn là bạn đang phân vân không biết nên marketing khách hàng mới như thế nào cho hiệu quả chính xác nhất? Vậy thì ngay

WARC-Type: response

Content-Type: application/http; msgtype=response

WARC-Truncated: length

WARC-Identified-Payload-Type: text/html

Server: cloudflare-nginx

Connection: close

X-CF-Powered-By: WP Rocket 2.10.7

Set-Cookie: __cfduid=de6ebb589447fc161e44174ae717b6d9f1505872350; expires=Thu, 20-Sep-18 01:52:30 GMT; path=/; domain=.tuhocmarketing.com; HttpOnly

Vary: Accept-Encoding

Content-Type: text/html; charset=UTF-8


text:
Câu hỏi
duc_tam379
30/07/2015 09:02
Ưu, nhược điểm iPhone 6 16GB
Danh sách câu trả lời (0)
Chưa có câu trả lời nào. Bạn hãy là người đầu tiên!
Trả lời câu hỏi
Câu hỏi lĩnh vực Điện thoại di động
Rao vặt Siêu Vip
- Cần gấp 1 nam ở ghép quận 2
- Cho thuê gấp nhà hẻm rộng 5m đường Nguyễn Bỉnh Khiêm, Quận 1 4.5m x 9.2m, 3 lầu, ST, 3PN, 4WC...
- BÁN GẤP NHÀ Trần Hưng Đạo P. Cầu kho, Q.1, DT 4.3mx13m, 4 lầu, Giá 4.1 tỷ.
- Khu dân cư Singa City đầu tư sinh lợi đất nền quận 9 thổ cư 100
- Bán nhà mặt tiền Trương Hoàng Thanh, P12, Tân Bình 4X20m, 3 lầu
- Đất 160m2 mặt tiền 6m shr thổ cư 100 ngay cuối phạm văn hai bình chánh
- Khởi đầu vinh hoa, bước đi phú quý, đất nền Đại Phúc chỉ 180tr/nền
- Chính chủ bán 2 lô đất khu dân cư An Hạ Residence giá 650tr/lô
- Bán nhà đúc 2 lầu, hẻm 437 Hàn Hải Nguyên, Q11. DT 3x12m. Giá 2,85 Tỷ
- Bán nhà thiết kế rất đẹp, theo phong thủy, khi trí thức.
- Cần Bán Nhà Gấp Khu An Ninh Yên Tịnh
- Nhà đường số 29 Tên Lửa, đổ 4 tấm , hẻm 8m thông thoáng.
- Cần bán Gấp 2 Lô Đất cuối Đường tân kỳ Tân quý.DT 10x20
- Mở bán trả góp tầng 8 căn hộ lotus Sen Hồng T Đức 623tr đã VAT trả trước 155tr ký hđ
- Shophouse của dự án căn hộ Sky Cente sân bay Tân Sơn Nhất
- S8 plus orchid gray tím khói bảo hành dài công ty
- Bán J7 Prime xịn nguyên hộp 5tr6
- Ip 7 Plus,Ip 7 128Gb Gold,Matte Black,Ip 6S Plus,Ip 6S Gold 16Gb,IP 6 PLus,Ip 64Gb.
- Cần bán lại Iphone 6 cũ, 128Gb, màu xám, bản Lock Nhật Bản. Giá mềm 3.5 triệu đồng.
- Khương Đình, Thanh Xuân, Cho thuê tầng 1 làm văn phòng, đường rộng 20 m, kinh doanh tốt

markdown:
Câu hỏi
![ avatar](/Content/images/no_photo.gif)
[duc_tam379](/Home/InfoAuthor?username=duc_tam379)
30/07/2015 09:02
# Ưu, nhược điểm iPhone 6 16GB
Danh sách câu trả lời (0)
Chưa có câu trả lời nào. Bạn hãy là người đầu tiên!
Trả lời câu hỏi
Câu hỏi lĩnh vực Điện thoại di động
Rao vặt Siêu Vip
[Cần gấp 1 nam ở ghép quận 2](/o-ghep-ho-chi-minh/can-gap-1-nam-o-ghep-quan-2-2482997.html) [Cho thuê gấp nhà hẻm rộng 5m đường Nguyễn Bỉnh Khiêm, Quận 1 4.5m x 9.2m, 3 lầu, ST, 3PN, 4WC...](/cho-thue-nha-rieng-ho-chi-minh/cho-thue-gap-nha-hem-rong-5m-duong-nguyen-binh-khi-2482900.html) [BÁN GẤP NHÀ Trần Hưng Đạo P. Cầu kho, Q.1, DT 4.3mx13m, 4 lầu, Giá 4.1 tỷ.](/ban-kho-nha-xuong-trang-trai-ho-chi-minh/ban-gap-nha-tran-hung-dao-p-cau-kho-q-1-dt-4-3m-2482858.html) [Khu dân cư Singa City đầu tư sinh lợi đất nền quận 9 thổ cư 100](/ban-dat-ho-chi-minh/khu-dan-cu-singa-city-dau-tu-sinh-loi-dat-nen-quan-2482755.html) [Bán nhà mặt tiền Trương Hoàng Thanh, P12, Tân Bình 4X20m, 3 lầu](/ban-dat-ho-chi-minh/ban-nha-mat-tien-truong-hoang-thanh-p12-tan-binh-2482742.html) [Đất 160m2 mặt tiền 6m shr thổ cư 100 ngay cuối phạm văn hai bình chánh](/ban-dat-ho-chi-minh/dat-160m2-mat-tien-6m-shr-tho-cu-100-ngay-cuoi-pha-2482739.html) [Khởi đầu vinh hoa, bước đi phú quý, đất nền Đại Phúc chỉ 180tr/nền](/ban-dat-ho-chi-minh/khoi-dau-vinh-hoa-buoc-di-phu-quy-dat-nen-dai-ph-2482711.html) [Chính chủ bán 2 lô đất khu dân cư An Hạ Residence giá 650tr/lô](/ban-biet-thu-lien-ke-ho-chi-minh/chinh-chu-ban-2-lo-dat-khu-dan-cu-an-ha-residence-2482678.html) [Bán nhà đúc 2 lầu, hẻm 437 Hàn Hải Nguyên, Q11. DT 3x12m. Giá 2,85 Tỷ](/ban-nha-rieng-ho-chi-minh/ban-nha-duc-2-lau-hem-437-han-hai-nguyen-q11-dt-2482622.html) [Bán nhà thiết kế rất đẹp, theo phong thủy, khi trí thức.](/ban-nha-rieng-ho-chi-minh/ban-nha-thiet-ke-rat-dep-theo-phong-thuy-khi-tri-2482606.html) [Cần Bán Nhà Gấp Khu An Ninh Yên Tịnh](/ban-nha-rieng-ho-chi-minh/can-ban-nha-gap-khu-an-ninh-yen-tinh-2482604.html) [Nhà đường số 29 Tên Lửa, đổ 4 tấm , hẻm 8m thông thoáng.](/ban-nha-rieng-ho-chi-minh/nha-duong-so-29-ten-lua-do-4-tam-hem-8m-thong-t-2482591.html) [Cần bán Gấp 2 Lô Đất cuối Đường tân kỳ Tân quý.DT 10x20](/ban-nha-mat-pho-ho-chi-minh/can-ban-gap-2-lo-dat-cuoi-duong-tan-ky-tan-quy-dt-2482551.html) [Mở bán trả góp tầng 8 căn hộ lotus Sen Hồng T Đức 623tr đã VAT trả trước 155tr ký hđ](/ban-can-ho-chung-cu-ho-chi-minh/mo-ban-tra-gop-tang-8-can-ho-lotus-sen-hong-t-duc-2482527.html) [Shophouse của dự án căn hộ Sky Cente sân bay Tân Sơn Nhất](/ban-can-ho-chung-cu-ho-chi-minh/shophouse-cua-du-an-can-ho-sky-cente-san-bay-tan-s-2482520.html) [S8 plus orchid gray tím khói bảo hành dài công ty](/dien-thoai-samsung-ha-noi/s8-plus-orchid-gray-tim-khoi-bao-hanh-dai-cong-ty-2482440.html) [Bán J7 Prime xịn nguyên hộp 5tr6](/dien-thoai-samsung-ha-noi/ban-j7-prime-xin-nguyen-hop-5tr6-2482439.html) [Ip 7 Plus,Ip 7 128Gb Gold,Matte Black,Ip 6S Plus,Ip 6S Gold 16Gb,IP 6 PLus,Ip 64Gb.](/dien-thoai-iphone-ha-noi/ip-7-plus-ip-7-128gb-gold-matte-black-ip-6s-plus-i-2482433.html) [Cần bán lại Iphone 6 cũ, 128Gb, màu xám, bản Lock Nhật Bản. Giá mềm 3.5 triệu đồng.](/dien-thoai-iphone-ha-noi/can-ban-lai-iphone-6-cu-128gb-mau-xam-ban-lock-2482430.html) [Khương Đình, Thanh Xuân, Cho thuê tầng 1 làm văn phòng, đường rộng 20 m, kinh doanh tốt](/cho-thue-nha-mat-pho-ha-noi/khuong-dinh-thanh-xuan-cho-thue-tang-1-lam-van-p-2482412.html)

WARC-Identified-Payload-Type: application/xhtml+xml

Cache-Control: private

Content-Type: text/html; charset=utf-8

Server: Vico Group

X-Frame-Options: SAMEORIGIN


text:
Trưa 19/10, tại khu nhà trọ ở phường Hưng Bình (thành phố Vinh, Nghệ An), nhiều nữ sinh túm tụm kể nhau nghe câu chuyện được chủ nhà trọ tặng quà 20/10. "Em chưa nhận được quà của người yêu, nhưng đã nhận quà của bác chủ nhà rồi...", một cô gái hóm hỉnh nói.
Nguyễn Thị Lương, sinh viên Cao đẳng Sư phạm Nghệ An kể, chiều 16/10 khi đang ngồi học bài thì nghe tiếng gõ cửa. Mở cửa, Lương thấy vợ chồng chủ nhà trọ Trần Quang Thanh nở nụ cười tươi rồi trao chiếc phong bì dán kỹ, nói rằng "đây là quà ngày 20/10". Vợ chồng ông Thanh lần lượt trao quà cho gần 10 phòng trọ của các nữ sinh trong khu trọ do mình quản lý.
Mở phong bì thư, Lương thấy 100.000 đồng cùng lá thư được đánh máy với câu từ rất cẩn thận. Đầu thư, ông Thanh chia sẻ: "Ngày 20/10 là ngày thành lập Hội liên hiệp Phụ nữ Việt Nam. Vào ngày này sinh thời Bác Hồ đã tặng phụ nữ Việt Nam 8 chữ vàng: Anh hùng, bất khuất, trung hậu, đảm đang...".
"Nhân dịp này, bác gửi đến các cháu nữ ở khu nhà trọ lời chúc mừng sức khỏe, hạnh phúc và may mắn. Bác mong các cháu phát huy truyền thống tốt đẹp của người phụ nữ Việt Nam, phấn đấu học tập, công tác thật tốt, xứng đáng là con cháu Bà Trưng, Bà Triệu...", ông chủ viết.
Phần nửa sau bức thư, ông Thanh nói: "Bác gửi các cháu món quà nhỏ để mua kẹo nhớ đến ngày 20/10. Một phần quan trọng nữa, bác mong các cháu nhớ mua ổ khóa xe để đảm bảo an toàn, ra vào phải tự khóa cổ. Xe máy là tài sản rất lớn mong các cháu đừng quá cẩu thả. Bác cháu ta cùng cố gắng xây dựng khu nhà trọ văn minh, vệ sinh và an toàn. Bắt tay các cháu!".
Nhận được món quà ý nghĩa, Lương đã chia sẻ hình ảnh lên Facebook. Rất nhiều người dành lời khen ngợi ông chủ nhà trọ vui tính.
Theo Lương, đây không phải lần đầu tiên ông Thanh viết tâm thư cho người thuê trọ. Trước đó vào cuối tháng 9, ông gửi thư tới mọi người với tiêu đề "Thư ngỏ số 3. Đừng để mất bò mới lo làm chuồng". Nội dung thư căn dặn mọi người hãy cẩn thận khóa cửa khi ra vào để bảo vệ tài sản.
"Hôm trước em thiếu ổ khóa xe, biết chuyện bác Thanh bảo ngồi xe máy bác chở tới chợ mua ổ khóa", Lương nói và cho biết rất cảm phục trước sự tận tình của ông chủ nhà. Những lần chưa có tiền trả thuê phòng, ông đều cho khất hoặc lùi thời hạn.
Nhiều nữ sinh cùng dãy nhà trọ đều nhận xét ông chủ nhà trọ từng trong quân ngũ rất tâm lý, luôn quan tâm tới những người thuê trọ. Nhiều hôm, ông còn đi gom rác cho 12 phòng trọ.
"Từ lúc đi học, em thuê trọ hàng chục nơi, nhưng chưa thấy ai chu đáo như bác Thanh", Đặng Thị Kim Chi (21 tuổi) chia sẻ.
Phương Linh

markdown:
Trưa 19/10, tại khu nhà trọ ở phường Hưng Bình (thành phố Vinh, Nghệ An), nhiều nữ sinh túm tụm kể nhau nghe câu chuyện được chủ nhà trọ tặng quà 20/10. "Em chưa nhận được quà của người yêu, nhưng đã nhận quà của bác chủ nhà rồi...", một cô gái hóm hỉnh nói.
Nguyễn Thị Lương, sinh viên Cao đẳng Sư phạm Nghệ An kể, chiều 16/10 khi đang ngồi học bài thì nghe tiếng gõ cửa. Mở cửa, Lương thấy vợ chồng chủ nhà trọ Trần Quang Thanh nở nụ cười tươi rồi trao chiếc phong bì dán kỹ, nói rằng "đây là quà ngày 20/10". Vợ chồng ông Thanh lần lượt trao quà cho gần 10 phòng trọ của các nữ sinh trong khu trọ do mình quản lý.
Mở phong bì thư, Lương thấy 100.000 đồng cùng lá thư được đánh máy với câu từ rất cẩn thận. Đầu thư, ông Thanh chia sẻ: "Ngày 20/10 là ngày thành lập Hội liên hiệp Phụ nữ Việt Nam. Vào ngày này sinh thời Bác Hồ đã tặng phụ nữ Việt Nam 8 chữ vàng: Anh hùng, bất khuất, trung hậu, đảm đang...".
"Nhân dịp này, bác gửi đến các cháu nữ ở khu nhà trọ lời chúc mừng sức khỏe, hạnh phúc và may mắn. Bác mong các cháu phát huy truyền thống tốt đẹp của người phụ nữ Việt Nam, phấn đấu học tập, công tác thật tốt, xứng đáng là con cháu Bà Trưng, Bà Triệu...", ông chủ viết.
Phần nửa sau bức thư, ông Thanh nói: "Bác gửi các cháu món quà nhỏ để mua kẹo nhớ đến ngày 20/10. Một phần quan trọng nữa, bác mong các cháu nhớ mua ổ khóa xe để đảm bảo an toàn, ra vào phải tự khóa cổ. Xe máy là tài sản rất lớn mong các cháu đừng quá cẩu thả. Bác cháu ta cùng cố gắng xây dựng khu nhà trọ văn minh, vệ sinh và an toàn. Bắt tay các cháu!".
|
|![]()
|
|
Nội dung bức thư ông Thanh gửi tới những nữ sinh viên tại khu nhà trọ nhân ngày 20/10. Ảnh:
Nhận được món quà ý nghĩa, Lương đã chia sẻ hình ảnh lên Facebook. Rất nhiều người dành lời khen ngợi ông chủ nhà trọ vui tính.
Theo Lương, đây không phải lần đầu tiên ông Thanh viết tâm thư cho người thuê trọ. Trước đó vào cuối tháng 9, ông gửi thư tới mọi người với tiêu đề "Thư ngỏ số 3. Đừng để mất bò mới lo làm chuồng". Nội dung thư căn dặn mọi người hãy cẩn thận khóa cửa khi ra vào để bảo vệ tài sản.
"Hôm trước em thiếu ổ khóa xe, biết chuyện bác Thanh bảo ngồi xe máy bác chở tới chợ mua ổ khóa", Lương nói và cho biết rất cảm phục trước sự tận tình của ông chủ nhà. Những lần chưa có tiền trả thuê phòng, ông đều cho khất hoặc lùi thời hạn.
Nhiều nữ sinh cùng dãy nhà trọ đều nhận xét ông chủ nhà trọ từng trong quân ngũ rất tâm lý, luôn quan tâm tới những người thuê trọ. Nhiều hôm, ông còn đi gom rác cho 12 phòng trọ.
"Từ lúc đi học, em thuê trọ hàng chục nơi, nhưng chưa thấy ai chu đáo như bác Thanh", Đặng Thị Kim Chi (21 tuổi) chia sẻ.
**Phương Linh**

server: nginx

Cache-Control: max-age=120, stale-while-revalidate=6, stale-if-error=864000, private

Set-Cookie: device_env=4; expires=Wed, 27-Sep-2017 02:21:59 GMT; path=/; domain=vnexpress.net


text:
Nhấn "Enter" hoặc "Trở lại" để bắt đầu tìm kiếm
Hãy tải ngay ứng dụng Dulux Visualizer về cho điện thoại và máy tính bảng của bạn.
Chúng tôi sẽ gửi cho bạn những tin tức đầy màu sắc từ bây giờ.

X-Content-Type-Options: nosniff

Cache-Control: public, max-age=86400

Set-Cookie: uid=CrYBl1nBzd4vOGqgCSOrAg==; path=/

Vary: Cookie, Accept-Encoding

Content-Language: vi