OpenCV實現圖像膨脹
圖像的膨脹與圖像腐蝕是一對相反的過程,與圖像腐蝕相似,圖像膨脹同樣需要結構元素用于控制圖像膨脹的效果。結構元素可以任意指定結構的中心點,并且結構元素的尺寸和具體內容都可以根據需求自己定義。定義結構元素之后,將結構元素的中心點依次放到圖像中每一個非0元素處,如果原圖像中某個元素被結構元素覆蓋,但是該像素的像素值不與結構元素中心點對應的像素點的像素值相同,那么將原圖像中的該像素的像素值修改為結構元素中心點對應點的像素值。圖像的膨脹過程示意圖如圖所示,圖中左側為待膨脹的原圖像,中間為結構元素,首先將結構元素的中心與原圖像中的A像素重合,將結構元素覆蓋的所有像素的像素值都修改為1,將結構元素中心點依次與原圖像中的每個像素重合,判斷是否有需要填充的像素。原圖像膨脹的結果如圖中右側圖像所示。

圖像膨脹數學表示形式如式(6.5)所示,通過公式可以發(fā)現,其實圖像A的膨脹運算就是生成能夠將結構元素B全部包含的圖像。

膨脹函數
void dilate( InputArray src, OutputArray dst, InputArray kernel,
Point anchor = Point(-1,-1), int iterations = 1,
int borderType = BORDER_CONSTANT,
const Scalar& borderValue = morphologyDefaultBorderValue() );
- src:輸入的待膨脹圖像,圖像的通道數可以是任意的,但是圖像的數據類型必須是CV_8U,CV_16U,CV_16S,CV_32F或CV_64F之一。
- dst:膨脹后的輸出圖像,與輸入圖像src具有相同的尺寸和數據類型。
- kernel:用于膨脹操作的結構元素,可以自己定義,也可以用getStructuringElement()函數生成。
- anchor:中心點在結構元素中的位置,默認參數為結構元素的幾何中心點
- iterations:膨脹的次數,默認值為1。
- borderType:像素外推法選擇標志,取值范圍在表3-5中給出。默認參數為BORDER_DEFAULT,表示不包含邊界值倒序填充。
- borderValue:使用邊界不變外推法時的邊界值。
該函數根據結構元素對輸入圖像進行膨脹,在膨脹多通道圖像時每個通道獨立進行膨脹運算。函數的第一個參數為待膨脹的圖像,圖像通道數可以是任意的,但是圖像的數據類型必須是CV_8U,CV_16U,CV_16S,CV_32F或CV_64F之一。函數第二個參數為膨脹后的輸出圖像,與輸入圖像具有相同的尺寸和數據類型。函數第三個和第四個參數都是與結構元素相關的參數,第三個參數為結構元素,膨脹時使用的結構元素尺寸越大效果越明顯,第四個參數為結構元素的中心位置,第四個參數的默認值為Point(-1,-1),表示結構元素的幾何中心處為結構元素的中心點。函數第五個參數是使用結構元素膨脹的次數,膨脹次數越多效果越明顯,默認參數為1,表示只膨脹1次。函數第六個參數是圖像像素外推法的選擇標志,第七個參數為使用邊界不變外推法時的邊界值,這兩個參數對圖像中主要部分的膨脹操作沒有影響,因此在多數情況下使用默認值即可。
簡單示例
//
// Created by smallflyfly on 2021/6/18.
//
#include "opencv2/opencv.hpp"
#include <iostream>
using namespace cv;
using namespace std;
void drawResult(Mat im, int num, Mat stats, Mat centroids, const string& name) {
for (int i = 1; i < num; ++i) {
int x = centroids.at<double>(i, 0);
int y = centroids.at<double>(i, 1);
cout << x << " " << y << endl;
circle(im, Point(x, y), 2, Scalar(0, 0, 255), -1);
int xmin = stats.at<int>(i, CC_STAT_LEFT);
int ymin = stats.at<int>(i, CC_STAT_TOP);
int w = stats.at<int>(i, CC_STAT_WIDTH);
int h = stats.at<int>(i, CC_STAT_HEIGHT);
Rect rect(xmin, ymin, w, h);
rectangle(im, rect, Scalar(255, 255, 255), 2);
putText(im, to_string(i), Point(x+5, y), FONT_HERSHEY_SCRIPT_SIMPLEX, 0.3, Scalar(0, 0, 255), 1);
}
imshow(name, im);
}
int main() {
Mat src = (
Mat_<uchar>(6, 6) <<
0, 0, 0, 0, 255, 0,
0, 255, 255, 255, 255, 255,
0, 255, 255, 255, 255, 0,
0, 255, 255, 255, 255, 0,
0, 255, 255, 255, 255, 0,
0, 0, 0, 0, 255, 0
);
resize(src, src, Size(0, 0), 50, 50, INTER_NEAREST);
Mat m1, m2;
m1 = getStructuringElement(0, Size(3, 3));
m2 = getStructuringElement(1, Size(3, 3));
Mat dilateM1, dilateM2;
dilate(src, dilateM1, m1, Point(-1, -1), 5);
dilate(src, dilateM2, m2, Point(-1, -1), 5);
imshow("src", src);
imshow("dilateM1", dilateM1);
imshow("dilateM2", dilateM2);
Mat xbim = imread("xiaobai.jpg");
Mat xbM1, xbM2;
dilate(xbim, xbM1, m1, Point(-1, -1), 2);
dilate(xbim, xbM2, m2, Point(-1, -1), 2);
imshow("xbim", xbim);
imshow("xbM1", xbM1);
imshow("xbM2", xbM2);
Mat im = imread("rice.jfif");
resize(im, im, Size(0, 0), 0.6, 0.6);
Mat im1 = im.clone();
Mat gray;
cvtColor(im, gray, CV_BGR2GRAY);
Mat riceBin;
threshold(gray, riceBin, 125, 255, THRESH_BINARY);
Mat out, stats, centroids;
int count1 = connectedComponentsWithStats(riceBin, out, stats, centroids, 8, CV_16U);
drawResult(im, count1, stats, centroids, "no dilate");
Mat dilateIm1, dilateIm2;
dilate(riceBin, dilateIm1, m1, Point(-1, -1), 5);
dilate(riceBin, dilateIm2, m2, Point(-1, -1), 5);
int count2 = connectedComponentsWithStats(dilateIm1, out, stats, centroids, 8, CV_16U);
drawResult(dilateIm1, count2, stats, centroids, "dilateIm1");
int count3 = connectedComponentsWithStats(dilateIm2, out, stats, centroids, 8, CV_16U);
drawResult(dilateIm2, count3, stats, centroids, "dilateIm2");
waitKey(0);
destroyAllWindows();
}

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關文章
C++ 11 std::function和std::bind使用詳解
這篇文章主要介紹了C++ 11 std::function和std::bind使用詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-02-02

