opencv之顏色過濾只留下圖片中的紅色區(qū)域操作
如圖,這次需要在圖片中找到卷尺的紅色刻度,所以需要對圖像做過濾,只留下紅色部分。

一開始的想法是分別找到RGB值,然后找到紅色區(qū)域的部分保留就可以了,不過好像很難確定紅色區(qū)域的RGB取值范圍,所以要把圖片轉(zhuǎn)化到HSV空間中去。
在opencv中直接使用cvCvtColor函數(shù)就可以啦。
IplImage* hsv = cvCreateImage( cvGetSize(image), 8, 3 );
cvCvtColor(image,hsv,CV_BGR2HSV);
opencv 的H范圍是0~180,紅色的H范圍大概是(0~8)∪(160,180) ,S是飽和度,一般是大于一個值,S過低就是灰色(參考值S>80),V是亮度,過低就是黑色,過高就是白色(參考值220>V>50)。
所以接下來要做的就是遍歷圖像,獲取圖像每個像素點的H,S,V分量,然后做判斷,滿足條件的就保留,不滿足的就賦值為黑色。
我是用opencv中的IplImage來存儲圖片的。
IplImage獲取像素點的方式如下:
CvScalar s_hsv = cvGet2D(hsv, j, i);//獲取像素點為(i, j)點的HSV的值,i是width值,j是height值
IplImage對像素點賦值的方式如下:
CvScalar s;
cvSet2D(hsv, j ,i, s);//對(i,j)處的像素點賦值
分別取得H,S,V分量,注意圖像轉(zhuǎn)化的時候BGR2HSV,所以s.val[0]是B或H的值,s.val[1]是G或S的值,s.val[2]則是R或V的值。
因為師弟喜歡用CvMat,所以輸入都改成了CvMat,使用的時候inputImage是希望過濾的圖片,outputImage則為輸出圖片,因為outputImage會在函數(shù)中進行空間申請與賦值,所以傳入?yún)?shù)的時候直接把它設(shè)成NULL就可以了。
另外要注意一點,因為是對彩色圖像做實驗,所以如果傳入的圖片不是3通道的彩色圖片,那么就會出內(nèi)存錯誤。
以下打開圖片或創(chuàng)建圖片的方式都是單通道方式,會出現(xiàn)內(nèi)存錯誤。
IplImage *input = cvLoadImage(path, 0),
CvMat* M = cvCreateMat(4,4,CV_32FC1); //或是8UC1, 因為C1表示nChannel = 1,也就是單通道
void colorFilter(CvMat *inputImage, CvMat *&outputImage)
{
int i, j;
IplImage* image = cvCreateImage(cvGetSize(inputImage), 8, 3);
cvGetImage(inputImage, image);
IplImage* hsv = cvCreateImage( cvGetSize(image), 8, 3 );
cvCvtColor(image,hsv,CV_BGR2HSV);
int width = hsv->width;
int height = hsv->height;
for (i = 0; i < height; i++)
for (j = 0; j < width; j++)
{
CvScalar s_hsv = cvGet2D(hsv, i, j);//獲取像素點為(j, i)點的HSV的值
/*
opencv 的H范圍是0~180,紅色的H范圍大概是(0~8)∪(160,180)
S是飽和度,一般是大于一個值,S過低就是灰色(參考值S>80),
V是亮度,過低就是黑色,過高就是白色(參考值220>V>50)。
*/
CvScalar s;
if (!(((s_hsv.val[0]>0)&&(s_hsv.val[0]<8)) || (s_hsv.val[0]>120)&&(s_hsv.val[0]<180)))
{
s.val[0] =0;
s.val[1]=0;
s.val[2]=0;
cvSet2D(hsv, i ,j, s);
}
}
outputImage = cvCreateMat( hsv->height, hsv->width, CV_8UC3 );
cvConvert(hsv, outputImage);
cvNamedWindow("filter");
cvShowImage("filter", hsv);
waitKey(0);
cvReleaseImage(&hsv);
}
關(guān)于函數(shù)還有一點要說明,H分量我取得是(0,8),(120,180),S與V分量沒有做篩選,如果按照注釋部分的進行篩選結(jié)果不是很好。
結(jié)果如圖:

補充知識:opencv實現(xiàn)圖像去除單一顏色背景
思路

因為背景是固定顏色,很容易篩選出背景,然后將其設(shè)為白色完全透明即可。
代碼
#coding=utf-8
import cv2 as cv
bg_color = [197, 102, 6]
threshold = 3000
def calc_diff(pixel):
'''
計算pixel與背景的離差平方和,作為當(dāng)前像素點與背景相似程度的度量
'''
return (pixel[0]-bg_color[0])**2 + (pixel[1]-bg_color[1])**2 + (pixel[2]-bg_color[2])**2
def remove_bg():
image_path = './logo.png'
logo = cv.imread(image_path)
logo = cv.cvtColor(logo, cv.COLOR_BGR2BGRA) #將圖像轉(zhuǎn)成帶透明通道的BGRA格式
h, w = logo.shape[0:2]
for i in range(h):
for j in range(w):
if calc_diff(logo[i][j]) < threshold:
#若果logo[i][j]為背景,將其顏色設(shè)為白色,且完全透明
logo[i][j][0] = 255
logo[i][j][1] = 255
logo[i][j][2] = 255
logo[i][j][3] = 0
cv.imwrite("./logo_rmbg.png", logo)
if __name__ == '__main__':
remove_bg()
使用方法
修改第5行的bg_color為圖片背景的bgr值,以及第6行的threshold(threshold越大,覆蓋的像素越多)。
效果:

emmm,事實證明背景附近的顏色不是嚴(yán)格的背景色,后來將字填充后好多了。

以上這篇opencv之顏色過濾只留下圖片中的紅色區(qū)域操作就是小編分享給大家的全部內(nèi)容了,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
在服務(wù)器端實現(xiàn)無間斷部署Python應(yīng)用的教程
這篇文章主要介紹了在服務(wù)器端實現(xiàn)無間斷部署Python應(yīng)用的教程,方法主要是Gunicorn進行重載,需要的朋友可以參考下2015-04-04
Python中函數(shù)的基本定義與調(diào)用及內(nèi)置函數(shù)詳解
這篇文章主要給大家介紹了關(guān)于Python中函數(shù)的基本定義與調(diào)用及內(nèi)置函數(shù)的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用Python具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-05-05

